<!-- The exported code uses Tailwind CSS. Install Tailwind CSS in your dev environment to ensure all styles work. -->
<template>
  <div class="min-h-screen bg-gray-50">
    <!-- 顶部导航栏 -->
    <Header />
    <!-- 左侧导航栏 -->
    <aside class="fixed left-0 top-16 bottom-0 w-64 bg-gray-800 text-white z-10 overflow-y-auto">
      <nav class="py-4">
        <div v-for="(menu, index) in mainMenus" :key="index" class="mb-1">
          <div class="flex items-center px-6 py-3 cursor-pointer hover:bg-gray-700"
            :class="{ 'bg-blue-700': menu.active }" @click="toggleMenu(index)">
            <i :class="menu.icon + ' mr-3 w-5 text-center'"></i>
            <span>{{ menu.name }}</span>
            <i class="fas fa-chevron-down ml-auto text-xs transition-transform duration-200"
              :class="{ 'transform rotate-180': menu.expanded }"></i>
          </div>
          <div v-if="menu.expanded" class="bg-gray-900">
            <div v-for="(submenu, subIndex) in menu.subMenus" :key="subIndex"
              class="flex items-center px-10 py-2 cursor-pointer hover:bg-gray-700"
              :class="{ 'text-blue-400': submenu.active }" @click="selectSubmenu(index, subIndex)">
              <a v-if="submenu.link" :href="submenu.link" data-readdy="true" class="text-sm w-full">{{ submenu.name
                }}</a>
              <span v-else class="text-sm">{{ submenu.name }}</span>
            </div>
          </div>
        </div>
      </nav>
    </aside>
    <!-- 主内容区域 -->
    <main class="pt-16 pl-64">
      <div class="container mx-auto p-6">
        <!-- 面包屑导航 -->
        <div class="flex items-center text-sm mb-4 text-gray-500">
          <span>首页</span>
          <i class="fas fa-chevron-right mx-2 text-xs"></i>
          <span>系统管理</span>
          <i class="fas fa-chevron-right mx-2 text-xs"></i>
          <span class="text-blue-600">数据管理</span>
        </div>
        <!-- 数据统计卡片 -->
        <div class="grid grid-cols-4 gap-4 mb-6">
          <!-- 数据总量卡片 -->
          <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
            <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-4">
              <i class="fas fa-database text-xl"></i>
            </div>
            <div>
              <div class="text-sm text-gray-500">数据总量</div>
              <div class="text-2xl font-bold text-gray-900">2,568</div>
              <div class="text-xs text-green-600 flex items-center">
                <i class="fas fa-arrow-up mr-1"></i> 环比增长 5.2%
              </div>
            </div>
          </div>
          <!-- 字段数量卡片 -->
          <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
            <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-4">
              <i class="fas fa-table text-xl"></i>
            </div>
            <div>
              <div class="text-sm text-gray-500">字段数量</div>
              <div class="text-2xl font-bold text-gray-900">156</div>
              <div class="text-xs text-green-600 flex items-center">
                <i class="fas fa-arrow-up mr-1"></i> 环比增长 2.8%
              </div>
            </div>
          </div>
          <!-- 同步状态卡片 -->
          <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
            <div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600 mr-4">
              <i class="fas fa-sync-alt text-xl"></i>
            </div>
            <div>
              <div class="text-sm text-gray-500">同步状态</div>
              <div class="text-2xl font-bold text-gray-900">正常</div>
              <div class="text-xs text-gray-500 flex items-center">
                <span>最近同步：2025-07-08 10:30</span>
              </div>
            </div>
          </div>
          <!-- 数据质量卡片 -->
          <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
            <div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600 mr-4">
              <i class="fas fa-chart-pie text-xl"></i>
            </div>
            <div>
              <div class="text-sm text-gray-500">数据质量</div>
              <div class="text-2xl font-bold text-gray-900">94.5%</div>
              <div class="text-xs text-red-600 flex items-center">
                <i class="fas fa-exclamation-circle mr-1"></i> 异常数据 24 条
              </div>
            </div>
          </div>
        </div>
        <!-- 筛选条件区域 -->
        <div v-if="activeTab === 'fields'" class="bg-white rounded-lg shadow-sm p-4 mb-6">
          <div class="flex flex-wrap items-center gap-4">
            <div class="flex items-center">
              <span class="text-gray-600 mr-2">数据类型：</span>
              <!-- 数据类型筛选 -->
              <div class="relative">
                <button
                  class="flex items-center justify-between w-48 px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer"
                  @click="showDataTypeFilter = !showDataTypeFilter">
                  <span class="text-gray-700">{{
                    selectedDataType || "请选择数据类型"
                  }}</span>
                  <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
                </button>
                <!-- 下拉菜单 -->
                <div v-if="showDataTypeFilter"
                  class="absolute top-full left-0 mt-1 w-48 bg-white border border-gray-300 rounded-lg shadow-lg z-20">
                  <div class="py-1">
                    <div v-for="type in dataTypes" :key="type"
                      class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                        'bg-blue-50 text-blue-600':
                          selectedDataType ===
                          (type === '全部类型' ? '' : type),
                      }" @click="selectDataType(type)">
                      {{ type }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div class="flex items-center">
              <span class="text-gray-600 mr-2">同步状态：</span>
              <!-- 同步状态筛选 -->
              <div class="relative">
                <button
                  class="flex items-center justify-between w-48 px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer"
                  @click="showStatusFilter = !showStatusFilter">
                  <span class="text-gray-700">{{
                    selectedStatus || "全部状态"
                    }}</span>
                  <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
                </button>
                <!-- 下拉菜单 -->
                <div v-if="showStatusFilter"
                  class="absolute top-full left-0 mt-1 w-48 bg-white border border-gray-300 rounded-lg shadow-lg z-20">
                  <div class="py-1">
                    <div v-for="status in statusTypes" :key="status"
                      class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                        'bg-blue-50 text-blue-600':
                          selectedStatus ===
                          (status === '全部状态' ? '' : status),
                      }" @click="selectStatus(status)">
                      {{ status }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div class="flex items-center ml-4">
              <div class="relative">
                <input type="text" v-model="searchKeyword" @keyup.enter="handleFieldSearch" placeholder="搜索数据名称/字段"
                  class="w-64 pl-10 pr-4 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
                <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
              </div>
            </div>
            <div class="ml-auto">
              <button
                class="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center !rounded-button whitespace-nowrap cursor-pointer"
                @click="showAddFieldModal = true">
                <i class="fas fa-plus mr-2"></i> 新建字段
              </button>
            </div>
          </div>
        </div>
        <!-- 标签页切换 -->
        <div class="bg-white rounded-lg shadow-sm mb-6">
          <div class="border-b border-gray-200">
            <nav class="flex -mb-px">
              <button v-for="(tab, index) in tabs" :key="index"
                class="py-4 px-6 font-medium text-sm border-b-2 focus:outline-none !rounded-button whitespace-nowrap cursor-pointer"
                :class="activeTab === tab.id
                  ? 'border-blue-500 text-blue-600'
                  : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
                  " @click="activeTab = tab.id">
                <i :class="tab.icon + ' mr-2'"></i>
                {{ tab.name }}
              </button>
            </nav>
          </div>
          <!-- 数据字段管理标签页 -->
          <div v-if="activeTab === 'fields'" class="p-4">
            <div class="overflow-x-auto">
              <table class="min-w-full divide-y divide-gray-200">
                <thead>
                  <tr>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider">
                      <div class="flex items-center">
                        <input type="checkbox" class="mr-2" @click="toggleSelectAll" :checked="isAllSelected" />
                        字段名称
                      </div>
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      字段标识
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      数据类型
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      是否必填
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      状态
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      更新时间
                    </th>
                    <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                      操作
                    </th>
                  </tr>
                </thead>
                <tbody class="bg-white divide-y divide-gray-200">
                  <tr v-for="(field, index) in paginatedFields" :key="index" class="hover:bg-gray-50">
                    <td class="px-4 py-3">
                      <div class="flex items-center">
                        <input type="checkbox" class="mr-3" v-model="field.selected" />
                        <div>
                          <div class="text-sm font-medium text-gray-900">
                            {{ field.name }}
                          </div>
                          <div class="text-xs text-gray-500">
                            {{ field.description }}
                          </div>
                        </div>
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="text-sm text-gray-900 text-left">
                        {{ field.identifier }}
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="text-sm text-gray-900 text-left">
                        {{ field.dataType }}
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="text-sm text-gray-900 text-left">
                        {{ field.isRequired ? "是" : "否" }}
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="flex items-center">
                        <div class="w-2 h-2 rounded-full mr-2" :class="field.status === '启用'
                          ? 'bg-green-500'
                          : 'bg-red-500'
                          "></div>
                        <span class="text-sm" :class="field.status === '启用'
                          ? 'text-green-600'
                          : 'text-red-600'
                          ">{{ field.status }}</span>
                      </div>
                    </td>
                    <td class="px-4 py-3">
                      <div class="text-sm text-gray-900 text-left">
                        {{ field.updateTime }}
                      </div>
                    </td>
                    <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                      <div class="flex space-x-2">
                        <button
                          class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                          @click="editField(field)">
                          <i class="fas fa-edit mr-1"></i> 编辑
                        </button>
                        <button class="hover:text-red-800 !rounded-button whitespace-nowrap cursor-pointer" :class="field.status === '启用'
                          ? 'text-red-600'
                          : 'text-green-600'
                          " @click="toggleFieldStatus(field)">
                          <i :class="field.status === '启用'
                            ? 'fas fa-ban mr-1'
                            : 'fas fa-check-circle mr-1'
                            "></i>
                          {{ field.status === "启用" ? "禁用" : "启用" }}
                        </button>
                      </div>
                    </td>
                  </tr>
                </tbody>
              </table>
              <!-- 数据字段管理标签页中的分页 -->
              <div class="flex justify-between items-center mt-4 px-4 py-3">
                <div class="flex items-center space-x-2">
                  <button
                    class="px-3 py-1 bg-gray-100 text-gray-700 rounded text-sm !rounded-button whitespace-nowrap cursor-pointer"
                    :disabled="!hasSelectedFields" :class="{
                      'opacity-50 cursor-not-allowed': !hasSelectedFields,
                    }" @click="batchDeleteFields">
                    批量删除
                  </button>
                  <button
                    class="px-3 py-1 bg-gray-100 text-gray-700 rounded text-sm !rounded-button whitespace-nowrap cursor-pointer"
                    :disabled="!hasSelectedFields" :class="{
                      'opacity-50 cursor-not-allowed': !hasSelectedFields,
                    }" @click="batchExportFields">
                    批量导出
                  </button>
                  <span class="text-sm text-gray-500 ml-2" v-if="hasSelectedFields">
                    已选择
                    <span class="text-blue-600">{{ selectedFieldsCount }}</span>
                    项
                  </span>
                </div>
                <Pagination :current-page="currentPage" :page-size="pageSize" :total="applyFieldFilters().length"
                  :page-sizes="pageSizes" @page-change="changePage" @page-size-change="changePageSize" />
              </div>
            </div>
          </div>
          <!-- 数据导入导出标签页 -->
          <div v-if="activeTab === 'import-export'" class="p-4">
            <div class="grid grid-cols-2 gap-6 mb-6">
              <!-- 数据导入卡片 -->
              <div class="bg-white rounded-lg shadow-sm p-6 border border-gray-200">
                <div class="flex items-center mb-4">
                  <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-4">
                    <i class="fas fa-file-import text-xl"></i>
                  </div>
                  <div>
                    <h3 class="text-lg font-medium text-gray-900">数据导入</h3>
                    <p class="text-sm text-gray-500">
                      支持 Excel、CSV、JSON 等多种格式导入
                    </p>
                  </div>
                </div>
                <div class="mt-6">
                  <div class="flex space-x-4 mb-4">
                    <button
                      class="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center justify-center !rounded-button whitespace-nowrap cursor-pointer"
                      @click="selectImportType('excel')">
                      <i class="fas fa-file-excel mr-2"></i> Excel 导入
                    </button>
                    <button
                      class="flex-1 px-4 py-2 bg-green-600 text-white rounded-lg flex items-center justify-center !rounded-button whitespace-nowrap cursor-pointer"
                      @click="selectImportType('csv')">
                      <i class="fas fa-file-csv mr-2"></i> CSV 导入
                    </button>
                  </div>
                  <div class="flex space-x-4">
                    <button
                      class="flex-1 px-4 py-2 bg-purple-600 text-white rounded-lg flex items-center justify-center !rounded-button whitespace-nowrap cursor-pointer"
                      @click="selectImportType('json')">
                      <i class="fas fa-file-code mr-2"></i> JSON 导入
                    </button>
                    <button
                      class="flex-1 px-4 py-2 bg-gray-600 text-white rounded-lg flex items-center justify-center !rounded-button whitespace-nowrap cursor-pointer"
                      @click="selectImportType('database')">
                      <i class="fas fa-database mr-2"></i> 数据库导入
                    </button>
                  </div>
                </div>
                <div class="mt-6">
                  <!-- 修改后的文件上传区域 -->
                  <div
                    class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-lg transition-all duration-200"
                    :class="{
                      'border-blue-400 bg-blue-50': isDragOver,
                      'border-green-400 bg-green-50': selectedFile
                    }" @drop.prevent="handleFileDrop" @dragover.prevent="handleDragOver"
                    @dragleave.prevent="handleDragLeave">
                    <div class="space-y-1 text-center" v-if="!selectedFile">
                      <i class="fas fa-cloud-upload-alt text-gray-400 text-3xl mb-2"></i>
                      <div class="flex text-sm text-gray-600 justify-center">
                        <label for="file-upload"
                          class="relative cursor-pointer bg-white rounded-md font-medium text-blue-600 hover:text-blue-500 focus-within:outline-none">
                          <span>上传文件</span>
                          <input id="file-upload" name="file-upload" type="file" class="sr-only"
                            @change="handleFileSelect" ref="fileInput" :accept="acceptedFileTypes" />
                        </label>
                        <p class="pl-1">或拖拽文件到此处</p>
                      </div>
                      <p class="text-xs text-gray-500">
                        支持单个或批量上传，单个文件不超过10MB
                      </p>
                      <p class="text-xs text-gray-500 mt-1">
                        当前选择: {{ selectedImportType }}
                      </p>
                    </div>

                    <!-- 文件已选择时的显示 -->
                    <div class="space-y-2 text-center" v-else>
                      <i class="fas fa-file text-green-500 text-3xl mb-2"></i>
                      <div class="text-sm font-medium text-gray-900">
                        {{ selectedFile.name }}
                      </div>
                      <div class="text-xs text-gray-500">
                        文件大小: {{ formatFileSize(selectedFile.size) }}
                      </div>
                      <div class="flex justify-center space-x-2 mt-2">
                        <button @click="removeFile" class="text-xs text-red-600 hover:text-red-800 cursor-pointer">
                          <i class="fas fa-times mr-1"></i>移除
                        </button>
                        <button @click="replaceFile" class="text-xs text-blue-600 hover:text-blue-800 cursor-pointer">
                          <i class="fas fa-sync mr-1"></i>更换
                        </button>
                      </div>
                    </div>
                  </div>

                  <!-- 错误提示 -->
                  <div v-if="fileError" class="mt-2 text-sm text-red-600 bg-red-50 p-2 rounded">
                    <i class="fas fa-exclamation-triangle mr-1"></i>
                    {{ fileError }}
                  </div>

                  <!-- 导入进度 -->
                  <div v-if="importProgress > 0" class="mt-4">
                    <div class="flex justify-between text-sm text-gray-600 mb-1">
                      <span>导入进度</span>
                      <span>{{ importProgress }}%</span>
                    </div>
                    <div class="w-full bg-gray-200 rounded-full h-2">
                      <div class="bg-blue-600 h-2 rounded-full transition-all duration-300"
                        :style="{ width: importProgress + '%' }"></div>
                    </div>
                  </div>

                  <div class="mt-4 flex justify-end">
                    <button
                      class="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center !rounded-button whitespace-nowrap cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
                      :disabled="!selectedFile || importProgress > 0" @click="startImport">
                      <i :class="[
                        importProgress > 0
                          ? 'fas fa-spinner fa-spin'
                          : 'fas fa-upload',
                        'mr-2',
                      ]"></i>
                      {{ importProgress > 0 ? "导入中..." : "开始导入" }}
                    </button>
                  </div>
                </div>
              </div>
              <!-- 数据导出卡片 -->
              <div class="bg-white rounded-lg shadow-sm p-6 border border-gray-200">
                <div class="flex items-center mb-4">
                  <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-4">
                    <i class="fas fa-file-export text-xl"></i>
                  </div>
                  <div>
                    <h3 class="text-lg font-medium text-gray-900">数据导出</h3>
                    <p class="text-sm text-gray-500">
                      支持多种格式导出，可自定义导出字段
                    </p>
                  </div>
                </div>
                <div class="mt-6">
                  <div class="mb-4 table-dropdown-container">
                    <label class="block text-sm font-medium text-gray-700 mb-1">选择数据表</label>
                    <div class="relative">
                      <button
                        class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer"
                        @click="showTableDropdown = !showTableDropdown">
                        <span class="text-gray-700">{{ exportForm.table || "请选择数据表" }}</span>
                        <i class="fas fa-chevron-down text-gray-500 text-xs"
                          :class="{ 'transform rotate-180': showTableDropdown }"></i>
                      </button>

                      <!-- 数据表下拉菜单 -->
                      <div v-if="showTableDropdown"
                        class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20 max-h-60 overflow-y-auto">
                        <div class="py-1">
                          <div v-for="table in dataTables" :key="table.id"
                            class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150"
                            :class="{ 'bg-blue-50 text-blue-600': exportForm.table === table.name }"
                            @click="selectTable(table)">
                            <div class="font-medium">{{ table.name }}</div>
                            <div class="text-xs text-gray-500">{{ table.description }}</div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div class="mb-4">
                    <label class="block text-sm font-medium text-gray-700 mb-1">导出范围</label>
                    <div class="flex space-x-4 mt-2">
                      <label class="flex items-center">
                        <input type="radio" name="exportRange" value="all" v-model="exportForm.range" class="mr-2" />
                        <span class="text-sm text-gray-700">全部数据</span>
                      </label>
                      <label class="flex items-center">
                        <input type="radio" name="exportRange" value="selected" v-model="exportForm.range"
                          class="mr-2" />
                        <span class="text-sm text-gray-700">选中数据</span>
                      </label>
                      <label class="flex items-center">
                        <input type="radio" name="exportRange" value="filtered" v-model="exportForm.range"
                          class="mr-2" />
                        <span class="text-sm text-gray-700">筛选数据</span>
                      </label>
                    </div>
                  </div>
                  <div class="mb-4">
                    <label class="block text-sm font-medium text-gray-700 mb-1">导出格式</label>
                    <div class="grid grid-cols-3 gap-2">
                      <button class="px-3 py-2 rounded-lg text-sm flex items-center justify-center transition-colors"
                        :class="exportForm.format === 'excel' ? 'bg-green-100 text-green-700 border border-green-300' : 'bg-gray-100 text-gray-700'"
                        @click="exportForm.format = 'excel'">
                        <i class="fas fa-file-excel mr-1 text-green-600"></i> Excel
                      </button>
                      <button class="px-3 py-2 rounded-lg text-sm flex items-center justify-center transition-colors"
                        :class="exportForm.format === 'csv' ? 'bg-blue-100 text-blue-700 border border-blue-300' : 'bg-gray-100 text-gray-700'"
                        @click="exportForm.format = 'csv'">
                        <i class="fas fa-file-csv mr-1 text-blue-600"></i> CSV
                      </button>
                      <button class="px-3 py-2 rounded-lg text-sm flex items-center justify-center transition-colors"
                        :class="exportForm.format === 'json' ? 'bg-purple-100 text-purple-700 border border-purple-300' : 'bg-gray-100 text-gray-700'"
                        @click="exportForm.format = 'json'">
                        <i class="fas fa-file-code mr-1 text-purple-600"></i> JSON
                      </button>
                    </div>
                  </div>
                </div>
                <div class="mt-6 flex justify-end">
                  <button
                    class="px-6 py-2 bg-green-600 text-white rounded-lg flex items-center hover:bg-green-700 transition-colors"
                    :disabled="isExporting" @click="startExport">
                    <i :class="isExporting ? 'fas fa-spinner fa-spin mr-2' : 'fas fa-download mr-2'"></i>
                    {{ isExporting ? '导出中...' : '开始导出' }}
                  </button>
                </div>
              </div>
            </div>
            <!-- 导入导出历史记录 -->
            <div class="bg-white rounded-lg shadow-sm p-4">
              <h3 class="text-lg font-medium text-gray-800 mb-3">
                导入导出历史
              </h3>
              <!-- 导入导出历史搜索框 -->
              <div class="mb-4">
                <div class="relative w-64">
                  <input type="text" v-model="importExportSearchKeyword" @keyup.enter="handleImportExportSearch"
                    placeholder="搜索任务名称/操作人"
                    class="w-full pl-10 pr-4 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
                  <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
                </div>
              </div>
              <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                  <thead>
                    <tr>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        任务名称
                      </th>

                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        任务类型
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        文件格式
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据量
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作人
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        状态
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作
                      </th>
                    </tr>
                  </thead>
                  <tbody class="bg-white divide-y divide-gray-200">
                    <tr v-for="(history, index) in paginatedHistory" :key="index" class="hover:bg-gray-50">
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-8 h-8 rounded-full flex items-center justify-center mr-3"
                            :class="getHistoryIconClass(history.type).bg">
                            <i :class="getHistoryIconClass(history.type).icon +
                              ' ' +
                              getHistoryIconClass(history.type).color
                              "></i>
                          </div>
                          <div class="text-sm font-medium text-gray-900">
                            {{ history.name }}
                          </div>
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ history.type }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ history.format }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ history.dataCount }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ history.operator }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ history.time }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-2 h-2 rounded-full mr-2" :class="history.status === '成功'
                            ? 'bg-green-500'
                            : history.status === '进行中'
                              ? 'bg-blue-500'
                              : 'bg-red-500'
                            "></div>
                          <span class="text-sm" :class="history.status === '成功'
                            ? 'text-green-600'
                            : history.status === '进行中'
                              ? 'text-blue-600'
                              : 'text-red-600'
                            ">{{ history.status }}</span>
                        </div>
                      </td>
                      <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                        <div class="flex space-x-2">
                          <button v-if="history.type === '导出'"
                            class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="downloadHistoryFile(history)">
                            <i class="fas fa-download mr-1"></i> 下载
                          </button>
                          <button
                            class="text-gray-600 hover:text-gray-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="viewHistoryDetail(history)">
                            <i class="fas fa-eye mr-1"></i> 详情
                          </button>
                          <button
                            class="text-red-600 hover:text-red-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="deleteHistoryRecord(history)">
                            <i class="fas fa-trash-alt mr-1"></i> 删除
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
                <!-- 导入导出历史记录分页 -->
                <div class="flex justify-end items-center mt-4 px-4 py-3">
                  <Pagination :current-page="currentPageHistory" :page-size="pageSizeHistory"
                    :total="filteredHistoryCount" :page-sizes="pageSizes" @page-change="changePageHistory"
                    @page-size-change="changePageSizeHistory" />
                </div>
              </div>
            </div>
            <!-- 历史记录详情弹窗 -->
            <div v-if="showHistoryDetailModal"
              class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
              <div class="bg-white rounded-lg p-6 w-[600px] max-h-[90vh] overflow-y-auto">
                <div class="flex justify-between items-center mb-4">
                  <h3 class="text-lg font-bold text-gray-800">历史记录详情</h3>
                  <button @click="showHistoryDetailModal = false"
                    class="text-gray-500 hover:text-gray-700 cursor-pointer">
                    <i class="fas fa-times"></i>
                  </button>
                </div>

                <div class="space-y-4">
                  <div class="grid grid-cols-2 gap-4">
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">任务名称</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.name }}</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">任务类型</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.type }}</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">文件格式</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.format }}</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">数据量</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.dataCount }} 条</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">操作人</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.operator }}</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">操作时间</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.time }}</div>
                    </div>
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">状态</label>
                      <div class="flex items-center">
                        <div class="w-2 h-2 rounded-full mr-2" :class="currentHistoryDetail.status === '成功'
                          ? 'bg-green-500'
                          : currentHistoryDetail.status === '进行中'
                            ? 'bg-blue-500'
                            : 'bg-red-500'
                          "></div>
                        <span class="text-sm" :class="currentHistoryDetail.status === '成功'
                          ? 'text-green-600'
                          : currentHistoryDetail.status === '进行中'
                            ? 'text-blue-600'
                            : 'text-red-600'
                          ">{{ currentHistoryDetail.status }}</span>
                      </div>
                    </div>
                    <div v-if="currentHistoryDetail.tableName">
                      <label class="block text-sm font-medium text-gray-700 mb-1">数据表</label>
                      <div class="text-sm text-gray-900">{{ currentHistoryDetail.tableName }}</div>
                    </div>
                  </div>
                  <div v-if="currentHistoryDetail.status === '失败'">
                    <label class="block text-sm font-medium text-gray-700 mb-1">失败原因</label>
                    <div class="text-sm text-red-600 bg-red-50 p-3 rounded-lg">
                      {{ getFailureReason(currentHistoryDetail) }}
                    </div>
                  </div>
                </div>

                <div class="flex justify-end mt-6">
                  <button @click="showHistoryDetailModal = false"
                    class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
                    关闭
                  </button>
                </div>
              </div>
            </div>
          </div>
          <!-- 数据清理标签页 -->
          <div v-if="activeTab === 'cleanup'" class="p-4">
            <div class="grid grid-cols-3 gap-4 mb-6">
              <div class="bg-white rounded-lg shadow-sm p-4">
                <h3 class="text-lg font-medium text-gray-800 mb-3">
                  数据质量分析
                </h3>
                <div ref="dataQualityChart" class="h-64"></div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4">
                <h3 class="text-lg font-medium text-gray-800 mb-3">
                  异常数据分布
                </h3>
                <div ref="dataAnomalyChart" class="h-64"></div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4">
                <h3 class="text-lg font-medium text-gray-800 mb-3">
                  数据完整性
                </h3>
                <div ref="dataCompletenessChart" class="h-64"></div>
              </div>
            </div>
            <!-- 数据清理任务 -->
            <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
              <div class="flex justify-between items-center mb-4">
                <h3 class="text-lg font-medium text-gray-800">数据清理任务</h3>
                <button
                  class="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center !rounded-button whitespace-nowrap cursor-pointer"
                  @click="showAddCleanupTaskModal = true">
                  <i class="fas fa-plus mr-2"></i> 新建清理任务
                </button>
              </div>
              <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                  <thead>
                    <tr>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        任务名称
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        清理类型
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        目标数据表
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        清理规则
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        创建时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        执行状态
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作
                      </th>
                    </tr>
                  </thead>
                  <tbody class="bg-white divide-y divide-gray-200">
                    <tr v-for="(task, index) in cleanupTasks" :key="index" class="hover:bg-gray-50">
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-8 h-8 rounded-full flex items-center justify-center mr-3"
                            :class="getCleanupIconClass(task.type).bg">
                            <i :class="getCleanupIconClass(task.type).icon +
                              ' ' +
                              getCleanupIconClass(task.type).color
                              "></i>
                          </div>
                          <div class="text-sm font-medium text-gray-900">
                            {{ task.name }}
                          </div>
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">{{ task.type }}</div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ task.targetTable }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">{{ task.rule }}</div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ task.createTime }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-2 h-2 rounded-full mr-2" :class="task.status === '已完成'
                            ? 'bg-green-500'
                            : task.status === '执行中'
                              ? 'bg-blue-500'
                              : 'bg-yellow-500'
                            "></div>
                          <span class="text-sm" :class="task.status === '已完成'
                            ? 'text-green-600'
                            : task.status === '执行中'
                              ? 'text-blue-600'
                              : 'text-yellow-600'
                            ">{{ task.status }}</span>
                        </div>
                      </td>
                      <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                        <div class="flex space-x-2">
                          <button v-if="task.status !== '执行中'"
                            class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="executeCleanupTask(task)">
                            <i class="fas fa-play mr-1"></i> 执行
                          </button>
                          <button v-else
                            class="text-yellow-600 hover:text-yellow-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="pauseCleanupTask(task)">
                            <i class="fas fa-pause mr-1"></i> 暂停
                          </button>
                          <button
                            class="text-gray-600 hover:text-gray-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="viewCleanupTaskResult(task)">
                            <i class="fas fa-eye mr-1"></i> 结果
                          </button>
                          <button
                            class="text-red-600 hover:text-red-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="deleteCleanupTask(task)">
                            <i class="fas fa-trash-alt mr-1"></i> 删除
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
            <!-- 数据异常记录 -->
            <div class="bg-white rounded-lg shadow-sm p-4">
              <h3 class="text-lg font-medium text-gray-800 mb-3">
                数据异常记录
              </h3>
              <!-- 数据异常记录搜索框 -->
              <div class="mb-4">
                <div class="relative w-64">
                  <input type="text" v-model="cleanupSearchKeyword" @keyup.enter="handleCleanupSearch"
                    placeholder="搜索数据ID/异常描述"
                    class="w-full pl-10 pr-4 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
                  <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
                </div>
              </div>
              <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                  <thead>
                    <tr>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据ID
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据表
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        异常类型
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        异常字段
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        异常描述
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        发现时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作
                      </th>
                    </tr>
                  </thead>
                  <tbody class="bg-white divide-y divide-gray-200">
                    <tr v-for="(anomaly, index) in paginatedAnomalies" :key="index" class="hover:bg-gray-50">
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ anomaly.dataId }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ anomaly.tableName }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-2 h-2 rounded-full mr-2" :class="getAnomalyTypeColor(anomaly.type)"></div>
                          <span class="text-sm text-gray-900">{{
                            anomaly.type
                            }}</span>
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 text-left">
                          {{ anomaly.field }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ anomaly.description }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ anomaly.discoveryTime }}
                        </div>
                      </td>
                      <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                        <div class="flex space-x-2">
                          <button
                            class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="fixAnomaly(anomaly)">
                            <i class="fas fa-wrench mr-1"></i> 修复
                          </button>
                          <button
                            class="text-gray-600 hover:text-gray-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="ignoreAnomaly(anomaly)">
                            <i class="fas fa-eye-slash mr-1"></i> 忽略
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
                <!-- 数据异常记录分页 -->
                <div class="flex justify-end items-center mt-4 px-4 py-3">
                  <Pagination :current-page="currentPageAnomaly" :page-size="pageSizeAnomaly"
                    :total="filteredAnomaliesCount" :page-sizes="pageSizes" @page-change="changePageAnomaly"
                    @page-size-change="changePageSizeAnomaly" />
                </div>
              </div>
            </div>
          </div>
          <!-- 数据同步标签页 -->
          <div v-if="activeTab === 'sync'" class="p-4">
            <!-- 同步状态概览 -->
            <div class="grid grid-cols-4 gap-4 mb-6">
              <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
                <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-4">
                  <i class="fas fa-sync-alt text-xl"></i>
                </div>
                <div>
                  <div class="text-sm text-gray-500">同步源数量</div>
                  <div class="text-2xl font-bold text-gray-900">6</div>
                  <div class="text-xs text-green-600 flex items-center">
                    <i class="fas fa-check-circle mr-1"></i> 全部正常
                  </div>
                </div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
                <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-4">
                  <i class="fas fa-calendar-check text-xl"></i>
                </div>
                <div>
                  <div class="text-sm text-gray-500">今日同步次数</div>
                  <div class="text-2xl font-bold text-gray-900">24</div>
                  <div class="text-xs text-blue-600 flex items-center">
                    <i class="fas fa-arrow-up mr-1"></i> 较昨日增加 3 次
                  </div>
                </div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
                <div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600 mr-4">
                  <i class="fas fa-exclamation-triangle text-xl"></i>
                </div>
                <div>
                  <div class="text-sm text-gray-500">同步异常</div>
                  <div class="text-2xl font-bold text-gray-900">2</div>
                  <div class="text-xs text-red-600 flex items-center">
                    <i class="fas fa-exclamation-circle mr-1"></i> 需要处理
                  </div>
                </div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4 flex items-center">
                <div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600 mr-4">
                  <i class="fas fa-clock text-xl"></i>
                </div>
                <div>
                  <div class="text-sm text-gray-500">下次同步时间</div>
                  <div class="text-2xl font-bold text-gray-900">15:30</div>
                  <div class="text-xs text-gray-500 flex items-center">
                    <span>2025-07-08</span>
                  </div>
                </div>
              </div>
            </div>
            <!-- 同步任务图表 -->
            <div class="grid grid-cols-2 gap-4 mb-6">
              <div class="bg-white rounded-lg shadow-sm p-4">
                <h3 class="text-lg font-medium text-gray-800 mb-3">
                  同步任务执行情况
                </h3>
                <div ref="syncTaskChart" class="h-64"></div>
              </div>
              <div class="bg-white rounded-lg shadow-sm p-4">
                <h3 class="text-lg font-medium text-gray-800 mb-3">
                  数据同步量趋势
                </h3>
                <div ref="syncVolumeChart" class="h-64"></div>
              </div>
            </div>
            <!-- 数据源配置 -->
            <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
              <div class="flex justify-between items-center mb-4">
                <h3 class="text-lg font-medium text-gray-800">数据源配置</h3>
                <button
                  class="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center !rounded-button whitespace-nowrap cursor-pointer"
                  @click="showAddDataSourceModal = true">
                  <i class="fas fa-plus mr-2"></i> 新增数据源
                </button>
              </div>
              <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                  <thead>
                    <tr>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据源名称
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据源类型
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        连接地址
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        同步方式
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        同步频率
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        最近同步时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        状态
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作
                      </th>
                    </tr>
                  </thead>
                  <tbody class="bg-white divide-y divide-gray-200">
                    <tr v-for="(source, index) in dataSources" :key="index" class="hover:bg-gray-50">
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-8 h-8 rounded-full flex items-center justify-center mr-3"
                            :class="getDataSourceIconClass(source.type).bg">
                            <i :class="getDataSourceIconClass(source.type).icon +
                              ' ' +
                              getDataSourceIconClass(source.type).color
                              "></i>
                          </div>
                          <div class="text-sm font-medium text-gray-900">
                            {{ source.name }}
                          </div>
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ source.type }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ source.connection }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ source.syncMethod }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ source.syncFrequency }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ source.lastSyncTime }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-2 h-2 rounded-full mr-2 justify-center" :class="source.status === '正常'
                            ? 'bg-green-500'
                            : source.status === '同步中'
                              ? 'bg-blue-500'
                              : 'bg-red-500'
                            "></div>
                          <span class="text-sm" :class="source.status === '正常'
                            ? 'text-green-600'
                            : source.status === '同步中'
                              ? 'text-blue-600'
                              : 'text-red-600'
                            ">{{ source.status }}</span>
                        </div>
                      </td>
                      <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                        <div class="flex space-x-2">
                          <button
                            class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="syncNow(source)">
                            <i class="fas fa-sync-alt mr-1"></i> 立即同步
                          </button>
                          <button
                            class="text-gray-600 hover:text-gray-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="editDataSource(source)">
                            <i class="fas fa-edit mr-1"></i> 编辑
                          </button>
                          <button
                            class="text-red-600 hover:text-red-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="deleteDataSource(source)">
                            <i class="fas fa-trash-alt mr-1"></i> 删除
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
            <!-- 同步日志 -->
            <div class="bg-white rounded-lg shadow-sm p-4">
              <h3 class="text-lg font-medium text-gray-800 mb-3">同步日志</h3>
              <!-- 同步日志搜索框 -->
              <div class="mb-4">
                <div class="relative w-64">
                  <input type="text" v-model="syncSearchKeyword" @keyup.enter="handleSyncSearch"
                    placeholder="搜索日志ID/数据源"
                    class="w-full pl-10 pr-4 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
                  <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
                </div>
              </div>
              <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                  <thead>
                    <tr>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        日志ID
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        数据源
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        同步类型
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        同步数据量
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        开始时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        结束时间
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        耗时
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        状态
                      </th>
                      <th class="px-4 py-3 bg-gray-50 text-xs font-medium text-gray-500 uppercase tracking-wider text-left">
                        操作
                      </th>
                    </tr>
                  </thead>
                  <tbody class="bg-white divide-y divide-gray-200">
                    <tr v-for="(log, index) in paginatedSyncLogs" :key="index" class="hover:bg-gray-50">
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">{{ log.id }}</div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.dataSource }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.syncType }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.dataVolume }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.startTime }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.endTime }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="text-sm text-gray-900 justify-center">
                          {{ log.duration }}
                        </div>
                      </td>
                      <td class="px-4 py-3">
                        <div class="flex items-center">
                          <div class="w-2 h-2 rounded-full mr-2" :class="log.status === '成功'
                            ? 'bg-green-500'
                            : log.status === '进行中'
                              ? 'bg-blue-500'
                              : 'bg-red-500'
                            "></div>
                          <span class="text-sm" :class="log.status === '成功'
                            ? 'text-green-600'
                            : log.status === '进行中'
                              ? 'text-blue-600'
                              : 'text-red-600'
                            ">{{ log.status }}</span>
                        </div>
                      </td>
                      <td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
                        <div class="flex space-x-2">
                          <button
                            class="text-gray-600 hover:text-gray-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="viewSyncLogDetail(log)">
                            <i class="fas fa-eye mr-1"></i> 详情
                          </button>
                          <button v-if="log.status === '失败'"
                            class="text-blue-600 hover:text-blue-800 !rounded-button whitespace-nowrap cursor-pointer"
                            @click="retrySyncLog(log)">
                            <i class="fas fa-redo mr-1"></i> 重试
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
                <!-- 同步日志分页 -->
                <div class="flex justify-end items-center mt-4 px-4 py-3">
                  <Pagination :current-page="currentPageSync" :page-size="pageSizeSync" :total="filteredSyncLogsCount"
                    :page-sizes="pageSizes" @page-change="changePageSync" @page-size-change="changePageSizeSync" />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
    <!-- 新建字段弹窗 -->
    <div v-if="showAddFieldModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[600px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">
            {{ editingField ? "编辑字段" : "新建字段" }}
          </h3>
          <button @click="showAddFieldModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="grid grid-cols-2 gap-4 mb-4">
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">字段名称</label>
            <input type="text" v-model="fieldForm.name" placeholder="请输入字段名称"
              class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
          </div>
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">字段标识</label>
            <input type="text" v-model="fieldForm.identifier" placeholder="请输入字段标识"
              class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
          </div>
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">数据类型</label>
            <div class="relative">
              <button
                class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer"
                @click="showDataTypeDropdown = !showDataTypeDropdown">
                <span class="text-gray-700">{{
                  fieldForm.dataType || "请选择数据类型"
                  }}</span>
                <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
              </button>
              <!-- 数据类型下拉菜单 -->
              <div v-if="showDataTypeDropdown"
                class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20">
                <div class="py-1">
                  <div v-for="type in dataTypes" :key="type"
                    class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                      'bg-blue-50 text-blue-600': fieldForm.dataType === type,
                    }" @click="selectFieldType(type)">
                    {{ type }}
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">是否必填</label>
            <div class="flex space-x-4 mt-2">
              <label class="flex items-center">
                <input type="radio" name="isRequired" :value="true" v-model="fieldForm.isRequired" class="mr-2" />
                <span class="text-sm text-gray-700">是</span>
              </label>
              <label class="flex items-center">
                <input type="radio" name="isRequired" :value="false" v-model="fieldForm.isRequired" class="mr-2" />
                <span class="text-sm text-gray-700">否</span>
              </label>
            </div>
          </div>
          <div class="col-span-2">
            <label class="block text-sm font-medium text-gray-700 mb-1">字段描述</label>
            <textarea v-model="fieldForm.description" placeholder="请输入字段描述"
              class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none"
              rows="3"></textarea>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">状态</label>
          <div class="flex space-x-4 mt-2">
            <label class="flex items-center">
              <input type="radio" name="status" value="启用" v-model="fieldForm.status" class="mr-2" />
              <span class="text-sm text-gray-700">启用</span>
            </label>
            <label class="flex items-center">
              <input type="radio" name="status" value="禁用" v-model="fieldForm.status" class="mr-2" />
              <span class="text-sm text-gray-700">禁用</span>
            </label>
          </div>
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showAddFieldModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            取消
          </button>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg !rounded-button whitespace-nowrap cursor-pointer"
            @click="saveField">
            确认
          </button>
        </div>
      </div>
    </div>
    <!-- 新建清理任务弹窗 -->
    <div v-if="showAddCleanupTaskModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[600px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">
            {{ editingCleanupTask ? "编辑清理任务" : "新建清理任务" }}
          </h3>
          <button @click="showAddCleanupTaskModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">任务名称</label>
          <input type="text" v-model="cleanupTaskForm.name" placeholder="请输入任务名称"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">清理类型</label>
          <div class="relative">
            <button @click="toggleCleanupTypeDropdown"
              class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer">
              <span class="text-gray-700">{{
                cleanupTaskForm.type || "请选择清理类型"
                }}</span>
              <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
            </button>
            <!-- 清理类型下拉菜单 -->
            <div v-if="showCleanupTypeDropdown"
              class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20">
              <div class="py-1">
                <div v-for="type in cleanupTypes" :key="type"
                  class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                    'bg-blue-50 text-blue-600': cleanupTaskForm.type === type,
                  }" @click="selectCleanupType(type)">
                  {{ type }}
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">目标数据表</label>
          <div class="relative">
            <button @click="toggleTargetTableDropdown"
              class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer">
              <span class="text-gray-700">{{
                cleanupTaskForm.targetTable || "请选择目标数据表"
                }}</span>
              <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
            </button>
            <!-- 目标数据表下拉菜单 -->
            <div v-if="showTargetTableDropdown"
              class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20">
              <div class="py-1">
                <div v-for="table in targetTables" :key="table"
                  class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                    'bg-blue-50 text-blue-600': cleanupTaskForm.targetTable === table,
                  }" @click="selectTargetTable(table)">
                  {{ table }}
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">清理规则</label>
          <textarea v-model="cleanupTaskForm.rule" placeholder="请输入清理规则"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none"
            rows="3"></textarea>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">执行方式</label>
          <div class="flex space-x-4 mt-2">
            <label class="flex items-center">
              <input type="radio" name="executionMethod" value="立即执行" v-model="cleanupTaskForm.executionMethod"
                class="mr-2" />
              <span class="text-sm text-gray-700">立即执行</span>
            </label>
            <label class="flex items-center">
              <input type="radio" name="executionMethod" value="定时执行" v-model="cleanupTaskForm.executionMethod"
                class="mr-2" />
              <span class="text-sm text-gray-700">定时执行</span>
            </label>
          </div>
        </div>
        <div v-if="cleanupTaskForm.executionMethod === '定时执行'" class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">执行时间</label>
          <input type="datetime-local" v-model="cleanupTaskForm.executionTime"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showAddCleanupTaskModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            取消
          </button>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg !rounded-button whitespace-nowrap cursor-pointer"
            @click="saveCleanupTask">
            确认
          </button>
        </div>
      </div>
    </div>
    <!-- 新增数据源弹窗 -->
    <div v-if="showAddDataSourceModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[600px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">
            {{ editingDataSource ? "编辑数据源" : "新增数据源" }}
          </h3>
          <button @click="showAddDataSourceModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">数据源名称</label>
          <input type="text" v-model="dataSourceForm.name" placeholder="请输入数据源名称"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">数据源类型</label>
          <div class="relative">
            <button @click="toggleDataSourceTypeDropdown"
              class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer">
              <span class="text-gray-700">{{
                dataSourceForm.type || "请选择数据源类型"
                }}</span>
              <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
            </button>
            <!-- 数据源类型下拉菜单 -->
            <div v-if="showDataSourceTypeDropdown"
              class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20">
              <div class="py-1">
                <div v-for="type in dataSourceTypes" :key="type"
                  class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                    'bg-blue-50 text-blue-600': dataSourceForm.type === type,
                  }" @click="selectDataSourceType(type)">
                  {{ type }}
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">连接地址</label>
          <input type="text" v-model="dataSourceForm.connection" placeholder="请输入连接地址"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
        </div>
        <div class="grid grid-cols-2 gap-4 mb-4">
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
            <input type="text" v-model="dataSourceForm.username" placeholder="请输入用户名"
              class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
          </div>
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-1">密码</label>
            <input type="password" v-model="dataSourceForm.password" placeholder="请输入密码"
              class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">同步方式</label>
          <div class="flex space-x-4 mt-2">
            <label class="flex items-center">
              <input type="radio" name="syncMethod" value="全量同步" v-model="dataSourceForm.syncMethod" class="mr-2" />
              <span class="text-sm text-gray-700">全量同步</span>
            </label>
            <label class="flex items-center">
              <input type="radio" name="syncMethod" value="增量同步" v-model="dataSourceForm.syncMethod" class="mr-2" />
              <span class="text-sm text-gray-700">增量同步</span>
            </label>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">同步频率</label>
          <div class="relative">
            <button @click="toggleSyncFrequencyDropdown"
              class="flex items-center justify-between w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg focus:outline-none !rounded-button whitespace-nowrap cursor-pointer">
              <span class="text-gray-700">{{
                dataSourceForm.syncFrequency || "请选择同步频率"
                }}</span>
              <i class="fas fa-chevron-down text-gray-500 text-xs"></i>
            </button>
            <!-- 同步频率下拉菜单 -->
            <div v-if="showSyncFrequencyDropdown"
              class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded-lg shadow-lg z-20">
              <div class="py-1">
                <div v-for="frequency in syncFrequencies" :key="frequency"
                  class="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm transition-colors duration-150" :class="{
                    'bg-blue-50 text-blue-600': dataSourceForm.syncFrequency === frequency,
                  }" @click="selectSyncFrequency(frequency)">
                  {{ frequency }}
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showAddDataSourceModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            取消
          </button>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg !rounded-button whitespace-nowrap cursor-pointer"
            @click="saveDataSource">
            确认
          </button>
        </div>
      </div>
    </div>
    <!-- 查看同步日志详情弹窗 -->
    <div v-if="showSyncLogDetailModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[700px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">同步日志详情</h3>
          <button @click="showSyncLogDetailModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="bg-gray-100 p-4 rounded-lg mb-4">
          <div class="grid grid-cols-2 gap-4">
            <div>
              <div class="text-sm text-gray-500">日志ID</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.id }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">数据源</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.dataSource }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">同步类型</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.syncType }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">同步数据量</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.dataVolume }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">开始时间</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.startTime }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">结束时间</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.endTime }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">耗时</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentSyncLog.duration }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">状态</div>
              <div class="flex items-center">
                <div class="w-2 h-2 rounded-full mr-2" :class="currentSyncLog.status === '成功'
                  ? 'bg-green-500'
                  : currentSyncLog.status === '进行中'
                    ? 'bg-blue-500'
                    : 'bg-red-500'
                  "></div>
                <span class="text-sm" :class="currentSyncLog.status === '成功'
                  ? 'text-green-600'
                  : currentSyncLog.status === '进行中'
                    ? 'text-blue-600'
                    : 'text-red-600'
                  ">{{ currentSyncLog.status }}</span>
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <h4 class="text-md font-medium text-gray-800 mb-2">同步详情</h4>
          <div class="bg-gray-100 p-4 rounded-lg">
            <div class="text-sm text-gray-700 whitespace-pre-line">
              {{ syncLogDetail }}
            </div>
          </div>
        </div>
        <div v-if="currentSyncLog.status === '失败'" class="mb-4">
          <h4 class="text-md font-medium text-gray-800 mb-2">错误信息</h4>
          <div class="bg-red-50 p-4 rounded-lg">
            <div class="text-sm text-red-700">{{ syncLogError }}</div>
          </div>
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showSyncLogDetailModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            关闭
          </button>
          <button v-if="currentSyncLog.status === '失败'"
            class="px-4 py-2 bg-blue-600 text-white rounded-lg !rounded-button whitespace-nowrap cursor-pointer"
            @click="retrySyncLog(currentSyncLog)">
            重试同步
          </button>
        </div>
      </div>
    </div>
    <!-- 查看清理任务结果弹窗 -->
    <div v-if="showCleanupTaskResultModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[700px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">清理任务结果</h3>
          <button @click="showCleanupTaskResultModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="bg-gray-100 p-4 rounded-lg mb-4">
          <div class="grid grid-cols-2 gap-4">
            <div>
              <div class="text-sm text-gray-500">任务名称</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentCleanupTask.name }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">清理类型</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentCleanupTask.type }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">目标数据表</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentCleanupTask.targetTable }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">执行状态</div>
              <div class="flex items-center">
                <div class="w-2 h-2 rounded-full mr-2" :class="currentCleanupTask.status === '已完成'
                  ? 'bg-green-500'
                  : currentCleanupTask.status === '执行中'
                    ? 'bg-blue-500'
                    : 'bg-yellow-500'
                  "></div>
                <span class="text-sm" :class="currentCleanupTask.status === '已完成'
                  ? 'text-green-600'
                  : currentCleanupTask.status === '执行中'
                    ? 'text-blue-600'
                    : 'text-yellow-600'
                  ">{{ currentCleanupTask.status }}</span>
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <h4 class="text-md font-medium text-gray-800 mb-2">清理结果统计</h4>
          <div class="grid grid-cols-3 gap-4">
            <div class="bg-blue-50 p-4 rounded-lg">
              <div class="text-sm text-gray-500">处理数据总量</div>
              <div class="text-xl font-medium text-blue-700">
                {{ cleanupTaskResult.totalProcessed }}
              </div>
            </div>
            <div class="bg-green-50 p-4 rounded-lg">
              <div class="text-sm text-gray-500">成功清理数据</div>
              <div class="text-xl font-medium text-green-700">
                {{ cleanupTaskResult.successCount }}
              </div>
            </div>
            <div class="bg-red-50 p-4 rounded-lg">
              <div class="text-sm text-gray-500">清理失败数据</div>
              <div class="text-xl font-medium text-red-700">
                {{ cleanupTaskResult.failCount }}
              </div>
            </div>
          </div>
        </div>
        <div class="mb-4">
          <h4 class="text-md font-medium text-gray-800 mb-2">清理详情</h4>
          <div class="bg-gray-100 p-4 rounded-lg">
            <div class="text-sm text-gray-700 whitespace-pre-line">
              {{ cleanupTaskDetail }}
            </div>
          </div>
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showCleanupTaskResultModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            关闭
          </button>
        </div>
      </div>
    </div>
    <!-- 修复数据异常弹窗 -->
    <div v-if="showFixAnomalyModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 w-[600px] max-h-[90vh] overflow-y-auto">
        <div class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-bold text-gray-800">修复数据异常</h3>
          <button @click="showFixAnomalyModal = false" class="text-gray-500 hover:text-gray-700 cursor-pointer">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="bg-gray-100 p-4 rounded-lg mb-4">
          <div class="grid grid-cols-2 gap-4">
            <div>
              <div class="text-sm text-gray-500">数据ID</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentAnomaly.dataId }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">数据表</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentAnomaly.tableName }}
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">异常类型</div>
              <div class="flex items-center justify-center">
                <div class="w-2 h-2 rounded-full mr-2" :class="getAnomalyTypeColor(currentAnomaly.type)"></div>
                <span class="text-sm text-gray-900">{{
                  currentAnomaly.type
                  }}</span>
              </div>
            </div>
            <div>
              <div class="text-sm text-gray-500">异常字段</div>
              <div class="text-sm font-medium text-gray-900">
                {{ currentAnomaly.field }}
              </div>
            </div>
          </div>
          <div class="mt-2">
            <div class="text-sm text-gray-500">异常描述</div>
            <div class="text-sm font-medium text-gray-900">
              {{ currentAnomaly.description }}
            </div>
          </div>
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">修复方式</label>
          <div class="flex space-x-4 mt-2">
            <label class="flex items-center">
              <input type="radio" name="fixMethod" value="手动修复" v-model="anomalyFixForm.method" class="mr-2" />
              <span class="text-sm text-gray-700">手动修复</span>
            </label>
            <label class="flex items-center">
              <input type="radio" name="fixMethod" value="自动修复" v-model="anomalyFixForm.method" class="mr-2" />
              <span class="text-sm text-gray-700">自动修复</span>
            </label>
          </div>
        </div>
        <div v-if="anomalyFixForm.method === '手动修复'" class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">修复值</label>
          <input type="text" v-model="anomalyFixForm.value" placeholder="请输入修复值"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none" />
        </div>
        <div class="mb-4">
          <label class="block text-sm font-medium text-gray-700 mb-1">修复备注</label>
          <textarea v-model="anomalyFixForm.remark" placeholder="请输入修复备注"
            class="w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm focus:outline-none border-none"
            rows="3"></textarea>
        </div>
        <div class="flex justify-end space-x-3">
          <button @click="showFixAnomalyModal = false"
            class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg !rounded-button whitespace-nowrap cursor-pointer">
            取消
          </button>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg !rounded-button whitespace-nowrap cursor-pointer"
            @click="confirmFixAnomaly">
            确认修复
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import * as echarts from "echarts";
import Header from "../components/Header.vue";
import Pagination from "../components/Pagination.vue";
import { ElMessage, ElMessageBox } from 'element-plus';
import { ElNotification } from 'element-plus';
export default {
  components: {
    Header,
    Pagination,
  },
  data() {
    return {
      selectedImportType: "未选择", // 添加导入类型选择
      selectedFile: null, // 添加选中的文件
      importProgress: 0, // 添加导入进度
      importTimer: null, // 添加导入定时器
      acceptedFileTypes: ".xlsx,.xls,.csv,.json", // 添加接受的文件类型
      isDragOver: false, // 拖拽状态
      fileError: "", // 文件错误信息
      // 数据表相关
      dataTables: [
        { id: 1, name: '安全生产数据表', description: '存储安全生产相关数据' },
        { id: 2, name: '设备数据表', description: '存储设备基本信息' },
        { id: 3, name: '人员数据表', description: '存储人员信息数据' },
        { id: 4, name: '报警记录表', description: '存储报警历史记录' },
        { id: 5, name: '安全检查表', description: '存储安全检查记录' },
        { id: 6, name: '维护记录表', description: '存储设备维护记录' }
      ],
      showTableDropdown: false,
      exportForm: {
        table: '',
        range: 'all', // 导出范围：all, selected, filtered
        format: 'excel' // 导出格式：excel, csv, json
      },
      isExporting: false, // 导出状态
      currentHistoryDetail: {}, // 当前查看的历史记录详情
      showHistoryDetailModal: false, // 历史记录详情弹窗显示状态
      activeTab: "fields",
      tabs: [
        { id: "fields", name: "数据字段管理", icon: "fas fa-table" },
        {
          id: "import-export",
          name: "数据导入导出",
          icon: "fas fa-exchange-alt",
        },
        { id: "cleanup", name: "数据清理", icon: "fas fa-broom" },
        { id: "sync", name: "数据同步", icon: "fas fa-sync-alt" },
      ],
      isAllSelected: false,
      // 添加分页相关数据
      currentPage: 1, // 字段管理当前页
      currentPageHistory: 1, // 导入导出历史当前页
      currentPageAnomaly: 1, // 异常数据当前页
      currentPageSync: 1, // 同步日志当前页
      pageSize: 5, // 字段管理每页条数
      pageSizeHistory: 5, // 导入导出历史每页条数
      pageSizeAnomaly: 5, // 异常数据每页条数
      pageSizeSync: 5, // 同步日志每页条数
      pageSizes: [5, 8], // 可选的每页条数
      showDataTypeFilter: false,
      showStatusFilter: false,
      selectedDataType: "",
      selectedStatus: "",
      // 添加搜索关键字
      searchKeyword: "",
      dataTypes: ["字符串", "整数", "浮点数", "日期时间", "文本"],
      statusTypes: [ "启用", "禁用"],
      // 新建字段表单相关
      showDataTypeDropdown: false,
      importExportSearchKeyword: "",
      cleanupSearchKeyword: "",
      syncSearchKeyword: "",
      showAddFieldModal: false,
      showAddCleanupTaskModal: false,
      showAddDataSourceModal: false,
      showSyncLogDetailModal: false,
      showCleanupTaskResultModal: false,
      showCleanupTypeDropdown: false,
      showTargetTableDropdown: false,
      showDataSourceTypeDropdown: false,
      showSyncFrequencyDropdown: false,
      showFixAnomalyModal: false,
      editingField: false,
      editingCleanupTask: false,
      editingDataSource: false,
      currentSyncLog: {},
      currentCleanupTask: {},
      currentAnomaly: {},
      fieldForm: {
        name: "",
        identifier: "",
        dataType: "",
        isRequired: false,
        description: "",
        status: "启用",
      },
      cleanupTaskForm: {
        name: "",
        type: "",
        targetTable: "",
        rule: "",
        executionMethod: "立即执行",
        executionTime: "",
      },
      cleanupTypes: [
        "重复数据清理",
        "无效数据清理",
        "数据归档",
        "数据标准化",
        "数据修复"
      ],
      targetTables: [
        "安全生产数据表",
        "设备数据表",
        "人员数据表",
        "报警记录表",
        "安全检查表",
        "设备维护记录表"
      ],
      dataSourceForm: {
        name: "",
        type: "",
        connection: "",
        username: "",
        password: "",
        syncMethod: "增量同步",
        syncFrequency: "每天",
      },
      dataSourceTypes: ["MySQL", "Oracle", "SQL Server", "PostgreSQL", "REST API"],
      syncFrequencies: ["每5分钟", "每15分钟", "每30分钟", "每小时", "每天", "每周"],
      anomalyFixForm: {
        method: "手动修复",
        value: "",
        remark: "",
      },
      syncLogDetail:
        "同步开始时间: 2025-07-08 10:30:15\n初始化连接...\n开始数据读取...\n读取表: safety_production_data\n处理数据: 2,568 条\n数据转换完成\n开始写入目标库...\n写入完成\n同步结束时间: 2025-07-08 10:32:45",
      syncLogError:
        "连接数据源失败: 无法连接到远程服务器，请检查网络连接或数据源配置。",
      cleanupTaskResult: {
        totalProcessed: 1256,
        successCount: 1240,
        failCount: 16,
      },
      cleanupTaskDetail:
        "清理任务开始时间: 2025-07-08 09:15:30\n开始扫描数据表: safety_production_data\n发现重复数据: 1,240 条\n开始清理重复数据...\n清理完成\n清理任务结束时间: 2025-07-08 09:18:45",
      mainMenus: [
        {
          name: "监测报警",
          icon: "fas fa-bell",
          expanded: false,
          active: false,
          subMenus: [
            { name: "数据汇聚功能", active: false, link: "/data-aggregation" },
            {
              name: "监测指标统计",
              active: false,
              link: "/monitoring-indicators",
            },
            { name: "区域化展示", active: false, link: "/regional-display" },
          ],
        },
        {
          name: "风险研判",
          icon: "fas fa-exclamation-triangle",
          expanded: false,
          active: false,
          subMenus: [
            { name: '智能风险评估', active: false, link: '/intelligent-risk-assessment' },
            { name: '预警信息推送', active: false, link: '/risk-warning-push' },
            { name: '风险管理与分析', active: true, link: '/risk-analysis' },
          ]
        },
        {
          name: "在线巡查",
          icon: "fas fa-search",
          expanded: false,
          active: false,
          subMenus: [
            {
              name: "企业信息汇总",
              active: false,
              link: "/summary-information",
            },
            { name: "巡查功能", active: false, link: "/patrol" },
            { name: "检索功能", active: false, link: "search" },
            { name: "一屏汇聚展示", active: false, link: "/screen-display" },
          ],
        },
        {
          name: "综合分析",
          icon: "fas fa-chart-line",
          expanded: false,
          active: false,
          subMenus: [
            { name: "联网与设备分析", active: false, link: "/equipment" },
            { name: "应用情况分析", active: false, link: "/application" },
            { name: "数据质量分析", active: false, link: "/data-quality" },
            { name: "定期专题报告", active: false, link: "report" },
          ],
        },
        {
          name: "系统管理",
          icon: "fas fa-cog",
          expanded: true,
          active: true,
          subMenus: [
            { name: "用户权限管理", active: false, link: "user-permission" },
            { name: "系统配置管理", active: false, link: "system-manage" },
            { name: "数据管理", active: true, link: "data-manage" },
            { name: "系统监控与维护", active: false, link: "monitoring" },
          ],
        },
      ],
      fields: [
        {
          id: 1,
          name: "设备编号",
          identifier: "device_id",
          dataType: "字符串",
          isRequired: true,
          description: "设备唯一标识编号",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 2,
          name: "设备名称",
          identifier: "device_name",
          dataType: "字符串",
          isRequired: true,
          description: "设备名称",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 3,
          name: "设备类型",
          identifier: "device_type",
          dataType: "字符串",
          isRequired: true,
          description: "设备类型分类",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 4,
          name: "安装位置",
          identifier: "install_location",
          dataType: "字符串",
          isRequired: true,
          description: "设备安装位置",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 5,
          name: "安装时间",
          identifier: "install_time",
          dataType: "日期时间",
          isRequired: true,
          description: "设备安装时间",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 6,
          name: "设备状态",
          identifier: "device_status",
          dataType: "整数",
          isRequired: true,
          description: "设备运行状态编码",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 7,
          name: "生产厂商",
          identifier: "manufacturer",
          dataType: "字符串",
          isRequired: false,
          description: "设备生产厂商",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 8,
          name: "维护周期",
          identifier: "maintenance_cycle",
          dataType: "整数",
          isRequired: false,
          description: "设备维护周期（天）",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 9,
          name: "报警阈值",
          identifier: "alarm_threshold",
          dataType: "浮点数",
          isRequired: false,
          description: "设备报警阈值",
          status: "禁用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
        {
          id: 10,
          name: "备注信息",
          identifier: "remarks",
          dataType: "文本",
          isRequired: false,
          description: "设备备注信息",
          status: "启用",
          updateTime: "2025-06-15 10:20:30",
          selected: false,
        },
      ],
      importExportHistory: this.loadImportExportHistory(),
      cleanupTasks: this.loadCleanupTasks(),
      dataAnomalies: [
        {
          id: 1,
          dataId: "DEV20250708001",
          tableName: "设备数据表",
          type: "数据缺失",
          field: "install_time",
          description: "安装时间字段值为空",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 2,
          dataId: "DEV20250708002",
          tableName: "设备数据表",
          type: "数据重复",
          field: "device_id",
          description: "设备编号重复，存在两条相同记录",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 3,
          dataId: "PER20250708001",
          tableName: "人员数据表",
          type: "数据异常",
          field: "phone_number",
          description: "手机号格式不正确",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 4,
          dataId: "PER20250708002",
          tableName: "人员数据表",
          type: "数据冲突",
          field: "employee_status",
          description: "员工状态为离职但在岗位表中仍为在职",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 5,
          dataId: "ALM20250708001",
          tableName: "报警记录表",
          type: "数据不一致",
          field: "alarm_level",
          description: "报警级别与报警类型不匹配",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 6,
          dataId: "CHK20250708001",
          tableName: "安全检查表",
          type: "数据过期",
          field: "next_check_date",
          description: "下次检查日期已过期但状态仍为正常",
          discoveryTime: "2025-07-08 08:30:15",
        },
        {
          id: 7,
          dataId: "DEV20250707001",
          tableName: "设备数据表",
          type: "数据缺失",
          field: "manufacturer",
          description: "生产厂商字段值为空",
          discoveryTime: "2025-07-07 14:20:30",
        },
        {
          id: 8,
          dataId: "PER20250707001",
          tableName: "人员数据表",
          type: "数据异常",
          field: "birth_date",
          description: "出生日期不合理（未来日期）",
          discoveryTime: "2025-07-07 10:15:45",
        },
      ],
      dataSources: [
        {
          id: 1,
          name: "生产数据库",
          type: "MySQL",
          connection: "jdbc:mysql://prod-db.example.com:3306/safety",
          syncMethod: "增量同步",
          syncFrequency: "每小时",
          lastSyncTime: "2025-07-08 10:30:00",
          status: "正常",
        },
        {
          id: 2,
          name: "设备数据接口",
          type: "REST API",
          connection: "https://api.devices.example.com/v1/data",
          syncMethod: "增量同步",
          syncFrequency: "每30分钟",
          lastSyncTime: "2025-07-08 10:30:00",
          status: "正常",
        },
        {
          id: 3,
          name: "人员管理系统",
          type: "Oracle",
          connection: "jdbc:oracle:thin:@hr-db.example.com:1521:HR",
          syncMethod: "全量同步",
          syncFrequency: "每天",
          lastSyncTime: "2025-07-08 00:00:00",
          status: "正常",
        },
        {
          id: 4,
          name: "报警数据源",
          type: "MongoDB",
          connection: "mongodb://alarm-db.example.com:27017/alarms",
          syncMethod: "增量同步",
          syncFrequency: "每5分钟",
          lastSyncTime: "2025-07-08 10:35:00",
          status: "同步中",
        },
        {
          id: 5,
          name: "历史数据仓库",
          type: "PostgreSQL",
          connection: "jdbc:postgresql://history-db.example.com:5432/history",
          syncMethod: "全量同步",
          syncFrequency: "每周",
          lastSyncTime: "2025-07-07 00:00:00",
          status: "正常",
        },
        {
          id: 6,
          name: "第三方安全检查系统",
          type: "SFTP",
          connection: "sftp://safety-check.example.com:22/data",
          syncMethod: "增量同步",
          syncFrequency: "每天",
          lastSyncTime: "2025-07-08 01:00:00",
          status: "异常",
        },
      ],
      syncLogs: [
        {
          id: "SYNC20250708001",
          dataSource: "生产数据库",
          syncType: "增量同步",
          dataVolume: "156条",
          startTime: "2025-07-08 10:30:00",
          endTime: "2025-07-08 10:32:45",
          duration: "2分45秒",
          status: "成功",
        },
        {
          id: "SYNC20250708002",
          dataSource: "设备数据接口",
          syncType: "增量同步",
          dataVolume: "42条",
          startTime: "2025-07-08 10:30:00",
          endTime: "2025-07-08 10:31:20",
          duration: "1分20秒",
          status: "成功",
        },
        {
          id: "SYNC20250708003",
          dataSource: "报警数据源",
          syncType: "增量同步",
          dataVolume: "18条",
          startTime: "2025-07-08 10:35:00",
          endTime: "",
          duration: "",
          status: "进行中",
        },
        {
          id: "SYNC20250708004",
          dataSource: "第三方安全检查系统",
          syncType: "增量同步",
          dataVolume: "0条",
          startTime: "2025-07-08 10:00:00",
          endTime: "2025-07-08 10:00:30",
          duration: "30秒",
          status: "失败",
        },
        {
          id: "SYNC20250708005",
          dataSource: "生产数据库",
          syncType: "增量同步",
          dataVolume: "128条",
          startTime: "2025-07-08 09:30:00",
          endTime: "2025-07-08 09:32:15",
          duration: "2分15秒",
          status: "成功",
        },
        {
          id: "SYNC20250708006",
          dataSource: "设备数据接口",
          syncType: "增量同步",
          dataVolume: "36条",
          startTime: "2025-07-08 09:30:00",
          endTime: "2025-07-08 09:31:05",
          duration: "1分05秒",
          status: "成功",
        },
        {
          id: "SYNC20250708007",
          dataSource: "人员管理系统",
          syncType: "全量同步",
          dataVolume: "342条",
          startTime: "2025-07-08 00:00:00",
          endTime: "2025-07-08 00:05:30",
          duration: "5分30秒",
          status: "成功",
        },
        {
          id: "SYNC20250707001",
          dataSource: "历史数据仓库",
          syncType: "全量同步",
          dataVolume: "1,256条",
          startTime: "2025-07-07 00:00:00",
          endTime: "2025-07-07 00:15:45",
          duration: "15分45秒",
          status: "成功",
        },
      ],
    };
  },
  computed: {
    hasSelectedFields() {
      return this.fields.some((field) => field.selected);
    },
    selectedFieldsCount() {
      return this.fields.filter((field) => field.selected).length;
    },
    // 添加分页计算属性
    paginatedFields() {
      // 应用筛选条件后的字段列表
      let filteredFields = this.applyFieldFilters();

      const start = (this.currentPage - 1) * this.pageSize;
      const end = start + this.pageSize;
      return filteredFields.slice(start, end);
    },
    paginatedHistory() {
      // 应用搜索条件后的导入导出历史记录
      let filteredHistory = [...this.importExportHistory];

      if (this.importExportSearchKeyword) {
        const searchTerm = this.importExportSearchKeyword.toLowerCase();
        filteredHistory = filteredHistory.filter(
          (history) =>
            history.name.toLowerCase().includes(searchTerm) ||
            history.operator.toLowerCase().includes(searchTerm)
        );
      }

      const start = (this.currentPageHistory - 1) * this.pageSizeHistory;
      const end = start + this.pageSizeHistory;
      return filteredHistory.slice(start, end);
    },
    paginatedAnomalies() {
      // 应用搜索条件后的数据异常记录
      let filteredAnomalies = [...this.dataAnomalies];

      if (this.cleanupSearchKeyword) {
        const searchTerm = this.cleanupSearchKeyword.toLowerCase();
        filteredAnomalies = filteredAnomalies.filter(
          (anomaly) =>
            anomaly.dataId.toLowerCase().includes(searchTerm) ||
            anomaly.description.toLowerCase().includes(searchTerm)
        );
      }

      const start = (this.currentPageAnomaly - 1) * this.pageSizeAnomaly;
      const end = start + this.pageSizeAnomaly;
      return filteredAnomalies.slice(start, end);
    },
    paginatedSyncLogs() {
      // 应用搜索条件后的同步日志
      let filteredLogs = [...this.syncLogs];

      if (this.syncSearchKeyword) {
        const searchTerm = this.syncSearchKeyword.toLowerCase();
        filteredLogs = filteredLogs.filter(
          (log) =>
            log.id.toLowerCase().includes(searchTerm) ||
            log.dataSource.toLowerCase().includes(searchTerm)
        );
      }

      const start = (this.currentPageSync - 1) * this.pageSizeSync;
      const end = start + this.pageSizeSync;
      return filteredLogs.slice(start, end);
    },
    // 修改分页总数计算，使用筛选后的数据
    totalPages() {
      const filteredFields = this.applyFieldFilters();
      return Math.ceil(filteredFields.length / this.pageSize);
    },
    totalPagesHistory() {
      return Math.ceil(this.filteredHistoryCount / this.pageSizeHistory);
    },
    totalPagesAnomaly() {
      return Math.ceil(this.filteredAnomaliesCount / this.pageSizeAnomaly);
    },
    totalPagesSync() {
      return Math.ceil(this.filteredSyncLogsCount / this.pageSizeSync);
    },

    // 确保这些筛选计数属性存在
    filteredHistoryCount() {
      let filteredHistory = [...this.importExportHistory];

      if (this.importExportSearchKeyword) {
        const searchTerm = this.importExportSearchKeyword.toLowerCase();
        filteredHistory = filteredHistory.filter(
          (history) =>
            history.name.toLowerCase().includes(searchTerm) ||
            history.operator.toLowerCase().includes(searchTerm)
        );
      }

      return filteredHistory.length;
    },

    filteredAnomaliesCount() {
      let filteredAnomalies = [...this.dataAnomalies];

      if (this.cleanupSearchKeyword) {
        const searchTerm = this.cleanupSearchKeyword.toLowerCase();
        filteredAnomalies = filteredAnomalies.filter(
          (anomaly) =>
            anomaly.dataId.toLowerCase().includes(searchTerm) ||
            anomaly.description.toLowerCase().includes(searchTerm)
        );
      }

      return filteredAnomalies.length;
    },

    filteredSyncLogsCount() {
      let filteredLogs = [...this.syncLogs];

      if (this.syncSearchKeyword) {
        const searchTerm = this.syncSearchKeyword.toLowerCase();
        filteredLogs = filteredLogs.filter(
          (log) =>
            log.id.toLowerCase().includes(searchTerm) ||
            log.dataSource.toLowerCase().includes(searchTerm)
        );
      }

      return filteredLogs.length;
    },
  },
  mounted() {
    this.$nextTick(() => {
      if (this.activeTab === "cleanup") {
        this.initCleanupCharts();
      } else if (this.activeTab === "sync") {
        this.initSyncCharts();
      }
    });
    // 添加点击外部关闭下拉菜单的事件监听
    document.addEventListener('click', this.handleClickOutside);
  },
  // 在组件销毁时移除事件监听
  beforeDestroy() {
    document.removeEventListener('click', this.handleClickOutside);
  },
  watch: {
    activeTab(newVal) {
      if (newVal === "cleanup") {
        this.$nextTick(() => {
          this.initCleanupCharts();
        });
      } else if (newVal === "sync") {
        this.$nextTick(() => {
          this.initSyncCharts();
        });
      }
    },
  },
  created() {
    // 从localStorage加载字段数据
    const savedFields = localStorage.getItem("dataManagementFields");
    if (savedFields) {
      try {
        this.fields = JSON.parse(savedFields);
      } catch (e) {
      }
    }
    // 从localStorage加载导入导出历史记录
    this.loadImportExportHistory();
    // 从localStorage加载清理任务数据
    this.loadCleanupTasks();
    // 从localStorage加载数据异常
    this.loadDataAnomaliesFromLocalStorage();
    // 从localStorage加载数据源
    this.loadDataSourcesFromLocalStorage();
    // 从localStorage加载同步日志
    this.loadSyncLogsFromLocalStorage();
  },
  methods: {
    // 处理拖拽进入
    handleDragOver() {
      this.isDragOver = true;
    },

    // 处理拖拽离开
    handleDragLeave() {
      this.isDragOver = false;
    },

    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes';
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },

    // 移除文件
    removeFile() {
      this.selectedFile = null;
      this.fileError = "";
      if (this.$refs.fileInput) {
        this.$refs.fileInput.value = "";
      }
    },

    // 更换文件
    replaceFile() {
      this.removeFile();
      // 触发文件选择
      this.$refs.fileInput?.click();
    },
    handleFileSelect(event) {
      const file = event.target.files[0];
      this.fileError = "";

      if (file) {
        // 文件大小验证
        if (file.size > 10 * 1024 * 1024) {
          this.fileError = "文件大小不能超过10MB";
          event.target.value = "";
          return;
        }

        // 文件类型验证
        const fileName = file.name.toLowerCase();
        const isValidType = this.validateFileType(fileName);

        if (!isValidType) {
          this.fileError = `不支持的文件类型，请选择${this.selectedImportType}格式的文件`;
          event.target.value = "";
          return;
        }

        this.selectedFile = file;
        this.isDragOver = false;
      }
    },

    // 验证文件类型
    validateFileType(fileName) {
      if (this.selectedImportType === "未选择") {
        return true; // 未选择类型时接受所有支持的类型
      }

      const typeMap = {
        "Excel": [".xlsx", ".xls"],
        "CSV": [".csv"],
        "JSON": [".json"]
      };

      const allowedExtensions = typeMap[this.selectedImportType] || [];
      return allowedExtensions.some(ext => fileName.endsWith(ext));
    },
    // 添加导入相关方法
    selectImportType(type) {
      const typeMap = {
        excel: "Excel",
        csv: "CSV",
        json: "JSON",
        database: "数据库",
      };
      this.selectedImportType = typeMap[type] || "未选择";
      // 设置接受的文件类型
      switch (type) {
        case "excel":
          this.acceptedFileTypes = ".xlsx,.xls";
          break;
        case "csv":
          this.acceptedFileTypes = ".csv";
          break;
        case "json":
          this.acceptedFileTypes = ".json";
          break;
        default:
          this.acceptedFileTypes = ".xlsx,.xls,.csv,.json";
      }
      // 重置文件选择
      this.selectedFile = null;
      if (this.$refs.fileInput) {
        this.$refs.fileInput.value = "";
      }
    },
    handleFileDrop(event) {
      this.isDragOver = false;
      const file = event.dataTransfer.files[0];

      if (file) {
        if (file.size > 10 * 1024 * 1024) {
          this.fileError = "文件大小不能超过10MB";
          return;
        }

        // 检查文件类型
        const fileName = file.name.toLowerCase();
        const isValidType = this.validateFileType(fileName);

        if (!isValidType) {
          this.fileError = `不支持的文件类型，请选择${this.selectedImportType}格式的文件`;
          return;
        }

        this.selectedFile = file;

        // 如果未选择导入类型，则根据文件扩展名自动选择
        if (this.selectedImportType === "未选择") {
          if (fileName.endsWith(".xlsx") || fileName.endsWith(".xls")) {
            this.selectedImportType = "Excel";
          } else if (fileName.endsWith(".csv")) {
            this.selectedImportType = "CSV";
          } else if (fileName.endsWith(".json")) {
            this.selectedImportType = "JSON";
          }
        }

        // 更新文件输入框
        if (this.$refs.fileInput) {
          const dataTransfer = new DataTransfer();
          dataTransfer.items.add(file);
          this.$refs.fileInput.files = dataTransfer.files;
        }
      }
    },
    // 开始导入数据
    startImport() {
      if (!this.selectedFile) {
        ElMessage.warning("请先选择要导入的文件");
        return;
      }
      if (this.selectedImportType === "未选择") {
        ElMessage.warning("请先选择导入类型");
        return;
      }
      // 模拟导入过程
      this.importProgress = 0;
      this.importTimer = setInterval(() => {
        this.importProgress += 10;
        if (this.importProgress >= 100) {
          clearInterval(this.importTimer);
          this.importTimer = null;

          // 添加导入记录到历史
          this.addImportRecord();

          // 显示导入完成提示
          setTimeout(() => {
            clearInterval(this.importTimer);
            this.importTimer = null;
            this.addImportRecord();
            ElMessage.success(`${this.selectedImportType}文件导入完成！`);
            this.importProgress = 0;
            this.selectedFile = null;
            this.selectedImportType = "未选择";
            if (this.$refs.fileInput) {
              this.$refs.fileInput.value = "";
            }
          }, 500);
        }
      }, 300);
    },
    addImportRecord() {
      // 生成随机数据量
      const dataCount = Math.floor(Math.random() * 1000) + 500;
      const status = Math.random() > 0.2 ? "成功" : Math.random() > 0.5 ? "失败" : "进行中";

      // 添加导入记录到历史
      this.importExportHistory.unshift({
        id: Date.now(), // 使用时间戳作为ID避免重复
        name: `${this.selectedImportType}数据导入`,
        type: "导入",
        format: this.selectedImportType === "Excel" ? "Excel" :
          this.selectedImportType === "CSV" ? "CSV" : "JSON",
        dataCount: dataCount.toString(),
        operator: "当前用户",
        time: new Date().toLocaleString("zh-CN", {
          year: "numeric",
          month: "2-digit",
          day: "2-digit",
          hour: "2-digit",
          minute: "2-digit",
          second: "2-digit"
        }).replace(/\//g, "-"),
        status: status,
      });

      // 保存到localStorage
      this.saveImportExportHistory();
    },
    selectTable(table) {
      this.exportForm.table = table.name;
      this.showTableDropdown = false;

      // 可以根据选中的表动态更新导出范围选项
      this.updateExportOptions(table);
    },
    // 根据选中的表更新导出选项
    updateExportOptions(table) {
      // 这里可以根据不同的表设置不同的默认选项


      // 示例：如果是设备数据表，默认选择全部数据
      if (table.name.includes('设备')) {
        this.exportForm.range = 'all';
      }
    },
    // 点击外部关闭下拉菜单
    handleClickOutside(event) {
      // 如果点击的不是下拉菜单内的元素，则关闭所有下拉菜单
      if (!event.target.closest('.relative')) {
        this.showDataTypeDropdown = false;
        this.showStatusFilter = false;
        this.showDataTypeFilter = false;
        this.showCleanupTypeDropdown = false;
        this.showTargetTableDropdown = false;
        this.showDataSourceTypeDropdown = false;
        this.showSyncFrequencyDropdown = false;
      }
    },
    // 开始导出数据
    startExport() {
      if (this.isExporting) return;
      if (!this.exportForm.table) {
        ElMessage.warning("请选择要导出的数据表");
        return;
      }
      this.isExporting = true;
      setTimeout(() => {
        this.isExporting = false;
        this.addExportRecord();
        ElMessage.success(`${this.exportForm.table} - ${this.getFormatName(this.exportForm.format)}文件导出成功！`);
      }, 2000);
    },
    // 获取格式名称
    getFormatName(format) {
      const formatMap = {
        excel: 'Excel',
        csv: 'CSV',
        json: 'JSON'
      };
      return formatMap[format] || '文件';
    },
    // 添加导出记录
    addExportRecord() {
      const dataCount = Math.floor(Math.random() * 1000) + 500;

      this.importExportHistory.unshift({
        id: Date.now(), // 使用时间戳作为ID避免重复
        name: `${this.exportForm.table} - ${this.getFormatName(this.exportForm.format)}导出`,
        type: '导出',
        format: this.getFormatName(this.exportForm.format),
        dataCount: dataCount.toString(),
        operator: '当前用户',
        time: new Date().toLocaleString('zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit'
        }).replace(/\//g, '-'),
        status: '成功',
        tableName: this.exportForm.table
      });

      // 保存到localStorage
      this.saveImportExportHistory();
    },
    // 获取失败原因
    getFailureReason(history) {
      // 根据历史记录类型返回相应的失败原因
      const reasons = {
        '导入': '文件格式不正确或数据验证失败',
        '导出': '数据源连接失败或文件生成错误'
      };
      return reasons[history.type] || '未知错误';
    },
    // 下载历史文件
    downloadHistoryFile(history) {
      if (history.status !== '成功') {
        ElMessage.warning('只有成功的导出记录才能下载文件');
        return;
      }
      // 模拟文件下载
      const fileName = `${history.name}_${history.time.replace(/[: ]/g, '-')}.${history.format.toLowerCase()}`;
      // 根据格式创建模拟文件内容
      let fileContent = '';
      let mimeType = '';

      switch (history.format.toLowerCase()) {
        case 'excel':
          // 这里实际应该从服务器获取文件
          fileContent = '模拟的Excel文件内容';
          mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
          break;
        case 'csv':
          fileContent = '字段1,字段2,字段3\n值1,值2,值3';
          mimeType = 'text/csv';
          break;
        case 'json':
          fileContent = JSON.stringify({
            exportTime: history.time,
            dataCount: history.dataCount,
            table: history.tableName || '未知表',
            records: []
          }, null, 2);
          mimeType = 'application/json';
          break;
        default:
          fileContent = '文件内容';
          mimeType = 'application/octet-stream';
      }
      // 创建下载链接
      const blob = new Blob([fileContent], { type: mimeType });
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);

      // 记录下载操作

    },
    // 查看历史详情
    viewHistoryDetail(history) {
      // 显示历史记录详情弹窗
      this.currentHistoryDetail = history;
      this.showHistoryDetailModal = true;
    },
    // 删除历史记录
    async deleteHistoryRecord(history) {
      try {
        await ElMessageBox.confirm(
          `确定要删除历史记录 "${history.name}" 吗？此操作不可恢复。`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
          }
        );

        this.importExportHistory = this.importExportHistory.filter(
          item => item.id !== history.id
        );
        this.saveImportExportHistory();
        ElMessage.success('历史记录删除成功');
      } catch (error) {
        // 用户点击取消

      }
    },
    // 从localStorage加载导入导出历史记录
    loadImportExportHistory() {
      try {
        const savedHistory = localStorage.getItem("dataManagementImportExportHistory");
        if (savedHistory) {
          return JSON.parse(savedHistory);
        }
      } catch (e) {

      }
      // 如果没有保存的历史记录，返回默认数据
      return [
        {
          id: 1,
          name: "安全生产数据导入",
          type: "导入",
          format: "Excel",
          dataCount: "1,256",
          operator: "管理员",
          time: "2025-07-08 09:30:15",
          status: "成功",
        },
        {
          id: 2,
          name: "设备数据导出",
          type: "导出",
          format: "CSV",
          dataCount: "568",
          operator: "管理员",
          time: "2025-07-08 08:45:20",
          status: "成功",
        },
        {
          id: 3,
          name: "人员数据导入",
          type: "导入",
          format: "JSON",
          dataCount: "342",
          operator: "张工程师",
          time: "2025-07-07 16:20:10",
          status: "失败",
        },
        {
          id: 4,
          name: "安全检查数据导出",
          type: "导出",
          format: "Excel",
          dataCount: "892",
          operator: "李安全",
          time: "2025-07-07 14:10:05",
          status: "成功",
        },
        {
          id: 5,
          name: "设备维护记录导入",
          type: "导入",
          format: "CSV",
          dataCount: "156",
          operator: "王维护",
          time: "2025-07-07 11:30:45",
          status: "成功",
        },
        {
          id: 6,
          name: "报警记录导出",
          type: "导出",
          format: "JSON",
          dataCount: "421",
          operator: "管理员",
          time: "2025-07-06 17:25:30",
          status: "成功",
        },
        {
          id: 7,
          name: "数据库全量导出",
          type: "导出",
          format: "SQL",
          dataCount: "2,568",
          operator: "系统管理员",
          time: "2025-07-06 02:00:00",
          status: "成功",
        },
        {
          id: 8,
          name: "历史数据导入",
          type: "导入",
          format: "Excel",
          dataCount: "1,024",
          operator: "张工程师",
          time: "2025-07-05 14:40:20",
          status: "进行中",
        },
      ];
    },
    // 保存导入导出历史记录到localStorage
    saveImportExportHistory() {
      try {
        localStorage.setItem(
          "dataManagementImportExportHistory",
          JSON.stringify(this.importExportHistory)
        );
      } catch (e) {

      }
    },
    // 添加加载清理任务数据的方法
    loadCleanupTasks() {
      const savedCleanupTasks = localStorage.getItem("dataManagementCleanupTasks");
      if (savedCleanupTasks) {
        return JSON.parse(savedCleanupTasks);
      }
      // 如果localStorage中没有数据，则返回默认数据
      return [
        {
          id: 1,
          name: "重复设备数据清理",
          type: "重复数据清理",
          targetTable: "设备数据表",
          rule: "根据设备编号去重，保留最新记录",
          createTime: "2025-07-08 09:00:00",
          status: "已完成",
        },
        {
          id: 2,
          name: "无效人员数据清理",
          type: "无效数据清理",
          targetTable: "人员数据表",
          rule: "清理离职人员数据，保留历史记录",
          createTime: "2025-07-07 14:30:00",
          status: "已完成",
        },
        {
          id: 3,
          name: "历史报警数据归档",
          type: "数据归档",
          targetTable: "报警记录表",
          rule: "归档30天前的报警数据",
          createTime: "2025-07-06 16:45:00",
          status: "执行中",
        },
        {
          id: 4,
          name: "数据格式标准化",
          type: "数据标准化",
          targetTable: "安全检查表",
          rule: "统一日期格式为YYYY-MM-DD",
          createTime: "2025-07-05 11:20:00",
          status: "待执行",
        },
        {
          id: 5,
          name: "缺失数据修复",
          type: "数据修复",
          targetTable: "设备维护记录表",
          rule: "填充缺失的维护人员信息",
          createTime: "2025-07-04 15:10:00",
          status: "已完成",
        },
      ];
    },
    // 添加应用字段筛选条件的方法
    applyFieldFilters() {
      let filteredFields = [...this.fields];

      // 数据类型筛选
      if (this.selectedDataType) {
        filteredFields = filteredFields.filter(
          (field) => field.dataType === this.selectedDataType
        );
      }
      // 状态筛选
      if (this.selectedStatus) {
        filteredFields = filteredFields.filter(
          (field) => field.status === this.selectedStatus
        );
      }
      // 搜索筛选
      if (this.searchKeyword) {
        const searchTerm = this.searchKeyword.toLowerCase();
        filteredFields = filteredFields.filter(
          (field) =>
            field.name.toLowerCase().includes(searchTerm) ||
            field.identifier.toLowerCase().includes(searchTerm) ||
            field.description.toLowerCase().includes(searchTerm)
        );
      }
      return filteredFields;
    },
    // 添加分页方法
    changePage(page) {
      if (page >= 1 && page <= this.totalPages) {
        this.currentPage = page;
      }
    },
    changePageSize(size) {
      this.pageSize = size;
      this.currentPage = 1;
    },
    changePageHistory(page) {
      if (page >= 1 && page <= this.totalPagesHistory) {
        this.currentPageHistory = page;
      }
    },
    changePageSizeHistory(size) {
      this.pageSizeHistory = size;
      this.currentPageHistory = 1;
    },
    changePageAnomaly(page) {
      if (page >= 1 && page <= this.totalPagesAnomaly) {
        this.currentPageAnomaly = page;
      }
    },
    changePageSizeAnomaly(size) {
      this.pageSizeAnomaly = size;
      this.currentPageAnomaly = 1;
    },
    changePageSync(page) {
      if (page >= 1 && page <= this.totalPagesSync) {
        this.currentPageSync = page;
      }
    },
    changePageSizeSync(size) {
      this.pageSizeSync = size;
      this.currentPageSync = 1;
    },
    selectDataType(type) {
      this.selectedDataType = type === "全部类型" ? "" : type;
      this.showDataTypeFilter = false;
      // 重置到第一页
      this.currentPage = 1;
    },
    selectStatus(status) {
      this.selectedStatus = status === "全部状态" ? "" : status;
      this.showStatusFilter = false;
      // 重置到第一页
      this.currentPage = 1;
    },
    // 选择字段类型
    selectFieldType(type) {
      this.fieldForm.dataType = type;
      this.showDataTypeDropdown = false;
    },
    toggleCleanupTypeDropdown() {
      // 关闭其他下拉菜单
      this.showTargetTableDropdown = false;
      // 切换当前下拉菜单
      this.showCleanupTypeDropdown = !this.showCleanupTypeDropdown;
    },
    selectCleanupType(type) {
      this.cleanupTaskForm.type = type;
      this.showCleanupTypeDropdown = false;
    },
    toggleTargetTableDropdown() {
      // 关闭其他下拉菜单
      this.showCleanupTypeDropdown = false;
      // 切换当前下拉菜单
      this.showTargetTableDropdown = !this.showTargetTableDropdown;
    },
    selectTargetTable(table) {
      this.cleanupTaskForm.targetTable = table;
      this.showTargetTableDropdown = false;
    },
    toggleDataSourceTypeDropdown() {
      // 关闭其他下拉菜单
      this.showSyncFrequencyDropdown = false;
      // 切换当前下拉菜单
      this.showDataSourceTypeDropdown = !this.showDataSourceTypeDropdown;
    },
    selectDataSourceType(type) {
      this.dataSourceForm.type = type;
      this.showDataSourceTypeDropdown = false;
    },
    toggleSyncFrequencyDropdown() {
      // 关闭其他下拉菜单
      this.showDataSourceTypeDropdown = false;
      // 切换当前下拉菜单
      this.showSyncFrequencyDropdown = !this.showSyncFrequencyDropdown;
    },
    selectSyncFrequency(frequency) {
      this.dataSourceForm.syncFrequency = frequency;
      this.showSyncFrequencyDropdown = false;
    },
    handleFieldSearch() {
      // 处理字段搜索
      this.currentPage = 1; // 重置到第一页
    },
    filterFields() {
      // 实现筛选逻辑
      this.currentPage = 1; // 重置到第一页
    },
    // 添加导入导出搜索处理方法
    handleImportExportSearch() {
      this.currentPageHistory = 1;
    },
    // 添加数据清理搜索处理方法
    handleCleanupSearch() {
      this.currentPageAnomaly = 1;
    },
    // 添加数据同步搜索处理方法
    handleSyncSearch() {
      this.currentPageSync = 1;
    },
    toggleMenu(index) {
      this.mainMenus[index].expanded = !this.mainMenus[index].expanded;
      // 如果展开了菜单，则将其他菜单收起
      if (this.mainMenus[index].expanded) {
        this.mainMenus.forEach((menu, i) => {
          if (i !== index) {
            menu.expanded = false;
          }
        });
      }
    },
    selectSubmenu(menuIndex, submenuIndex) {
      // 重置所有菜单的激活状态
      this.mainMenus.forEach((menu) => {
        menu.active = false;
        menu.subMenus.forEach((submenu) => {
          submenu.active = false;
        });
      });
      // 设置当前选中的菜单和子菜单为激活状态
      this.mainMenus[menuIndex].active = true;
      this.mainMenus[menuIndex].subMenus[submenuIndex].active = true;
    },
    toggleSelectAll() {
      this.isAllSelected = !this.isAllSelected;
      this.fields.forEach((field) => {
        field.selected = this.isAllSelected;
      });
    },
    editField(field) {
      this.editingField = true;
      this.fieldForm = {
        id: field.id, // 确保包含id
        name: field.name,
        identifier: field.identifier,
        dataType: field.dataType,
        isRequired: field.isRequired,
        description: field.description,
        status: field.status,
      };
      this.showAddFieldModal = true;
    },
    toggleFieldStatus(field) {
      field.status = field.status === "启用" ? "禁用" : "启用";
      // 保存到localStorage
      this.saveFieldsToLocalStorage();
    },
    saveField() {
      // 添加表单验证逻辑
      if (!this.fieldForm.name) {
        ElMessage.warning("请输入字段名称");
        return;
      }
      if (!this.fieldForm.identifier) {
        ElMessage.warning("请输入字段标识");
        return;
      }
      if (!this.fieldForm.dataType) {
        ElMessage.warning("请选择数据类型");
        return;
      }
      if (!this.fieldForm.description) {
        ElMessage.warning("请输入字段描述");
        return;
      }

      // 检查字段标识是否已存在（编辑模式下排除当前字段）
      const existingField = this.fields.find(
        (field) =>
          field.identifier === this.fieldForm.identifier &&
          (!this.editingField || field.id !== this.fieldForm.id)
      );

      if (existingField) {
        ElMessage.warning("字段标识已存在，请使用其他标识");
        return;
      }
      if (this.editingField) {
        // 编辑现有字段
        const index = this.fields.findIndex(
          (field) => field.id === this.fieldForm.id
        );
        if (index !== -1) {
          this.fields[index] = {
            ...this.fieldForm,
            updateTime: this.getCurrentTime(),
          };
        }
      } else {
        // 添加新字段
        const newField = {
          id: this.generateFieldId(),
          name: this.fieldForm.name,
          identifier: this.fieldForm.identifier,
          dataType: this.fieldForm.dataType,
          isRequired: this.fieldForm.isRequired,
          description: this.fieldForm.description,
          status: this.fieldForm.status,
          updateTime: this.getCurrentTime(),
          selected: false,
        };
        this.fields.unshift(newField); // 添加到数组开头
      }

      // 保存到localStorage
      this.saveFieldsToLocalStorage();
      this.showAddFieldModal = false;
      this.editingField = false;
      this.fieldForm = {
        name: "",
        identifier: "",
        dataType: "",
        isRequired: false,
        description: "",
        status: "启用",
      };
    },
    // 添加辅助方法
    generateFieldId() {
      return Math.max(...this.fields.map((field) => field.id), 0) + 1;
    },
    generateCleanupTaskId() {
      return Math.max(...this.cleanupTasks.map((task) => task.id), 0) + 1;
    },
    generateDataSourceId() {
      return Math.max(...this.dataSources.map((source) => source.id), 0) + 1;
    },
    getCurrentTime() {
      const now = new Date();
      return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(
        2,
        "0"
      )}-${String(now.getDate()).padStart(2, "0")} ${String(
        now.getHours()
      ).padStart(2, "0")}:${String(now.getMinutes()).padStart(
        2,
        "0"
      )}:${String(now.getSeconds()).padStart(2, "0")}`;
    },
    // 保存字段数据到localStorage
    saveFieldsToLocalStorage() {
      try {
        localStorage.setItem(
          "dataManagementFields",
          JSON.stringify(this.fields)
        );
      } catch (e) {
      }
    },
    // 保存清理任务数据到localStorage
    saveCleanupTasksToLocalStorage() {
      try {
        localStorage.setItem(
          "dataManagementCleanupTasks",
          JSON.stringify(this.cleanupTasks)
        );
      } catch (e) {

      }
    },
    // 保存数据源到localStorage
    saveDataSourcesToLocalStorage() {
      try {
        localStorage.setItem(
          "dataManagementDataSources",
          JSON.stringify(this.dataSources)
        );
      } catch (e) {

      }
    },
    // 从localStorage加载数据源
    loadDataSourcesFromLocalStorage() {
      try {
        const savedDataSources = localStorage.getItem("dataManagementDataSources");
        if (savedDataSources) {
          this.dataSources = JSON.parse(savedDataSources);
        }
      } catch (e) {

      }
    },
    // 保存同步日志到localStorage
    saveSyncLogsToLocalStorage() {
      try {
        localStorage.setItem(
          "dataManagementSyncLogs",
          JSON.stringify(this.syncLogs)
        );
      } catch (e) {

      }
    },
    // 从localStorage加载同步日志
    loadSyncLogsFromLocalStorage() {
      try {
        const savedSyncLogs = localStorage.getItem("dataManagementSyncLogs");
        if (savedSyncLogs) {
          this.syncLogs = JSON.parse(savedSyncLogs);
        }
      } catch (e) {

      }
    },
    getHistoryIconClass(type) {
      const classes = {
        导入: {
          bg: "bg-blue-100",
          icon: "fas fa-file-import",
          color: "text-blue-600",
        },
        导出: {
          bg: "bg-green-100",
          icon: "fas fa-file-export",
          color: "text-green-600",
        },
      };
      return (
        classes[type] || {
          bg: "bg-gray-100",
          icon: "fas fa-file",
          color: "text-gray-600",
        }
      );
    },
    getCleanupIconClass(type) {
      const classes = {
        重复数据清理: {
          bg: "bg-blue-100",
          icon: "fas fa-clone",
          color: "text-blue-600",
        },
        无效数据清理: {
          bg: "bg-red-100",
          icon: "fas fa-trash-alt",
          color: "text-red-600",
        },
        数据归档: {
          bg: "bg-yellow-100",
          icon: "fas fa-archive",
          color: "text-yellow-600",
        },
        数据标准化: {
          bg: "bg-green-100",
          icon: "fas fa-check-square",
          color: "text-green-600",
        },
        数据修复: {
          bg: "bg-purple-100",
          icon: "fas fa-wrench",
          color: "text-purple-600",
        },
      };
      return (
        classes[type] || {
          bg: "bg-gray-100",
          icon: "fas fa-broom",
          color: "text-gray-600",
        }
      );
    },
    getDataSourceIconClass(type) {
      const classes = {
        MySQL: {
          bg: "bg-blue-100",
          icon: "fas fa-database",
          color: "text-blue-600",
        },
        "REST API": {
          bg: "bg-green-100",
          icon: "fas fa-cloud",
          color: "text-green-600",
        },
        Oracle: {
          bg: "bg-red-100",
          icon: "fas fa-database",
          color: "text-red-600",
        },
        MongoDB: {
          bg: "bg-green-100",
          icon: "fas fa-leaf",
          color: "text-green-600",
        },
        PostgreSQL: {
          bg: "bg-blue-100",
          icon: "fas fa-database",
          color: "text-blue-600",
        },
        SFTP: {
          bg: "bg-yellow-100",
          icon: "fas fa-file-upload",
          color: "text-yellow-600",
        },
      };
      return (
        classes[type] || {
          bg: "bg-gray-100",
          icon: "fas fa-database",
          color: "text-gray-600",
        }
      );
    },
    getAnomalyTypeColor(type) {
      const colors = {
        数据缺失: "bg-red-500",
        数据重复: "bg-orange-500",
        数据异常: "bg-yellow-500",
        数据冲突: "bg-purple-500",
        数据不一致: "bg-blue-500",
        数据过期: "bg-gray-500",
      };
      return colors[type] || "bg-gray-500";
    },
    executeCleanupTask(task) {
      task.status = "执行中";
    },
    pauseCleanupTask(task) {
      task.status = "已暂停";
      // 保存到localStorage
      this.saveCleanupTasksToLocalStorage();
    },
    viewCleanupTaskResult(task) {
      this.currentCleanupTask = task;
      this.showCleanupTaskResultModal = true;
    },
    async deleteCleanupTask(task) {
      try {
        await ElMessageBox.confirm(
          `确定要删除清理任务 "${task.name}" 吗？此操作不可恢复。`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
          }
        );

        this.cleanupTasks = this.cleanupTasks.filter((t) => t.id !== task.id);
        this.saveCleanupTasksToLocalStorage();
        ElMessage.success('清理任务删除成功');
      } catch (error) {
        // 用户点击取消

      }
    },
    saveCleanupTask() {
      // 添加表单验证逻辑
      if (!this.cleanupTaskForm.name) {
        ElMessage.warning("请输入任务名称");
        return;
      }
      if (!this.cleanupTaskForm.type) {
        ElMessage.warning("请选择清理类型");
        return;
      }
      if (!this.cleanupTaskForm.targetTable) {
        ElMessage.warning("请选择目标数据表");
        return;
      }
      if (!this.cleanupTaskForm.rule) {
        ElMessage.warning("请输入清理规则");
        return;
      }

      if (this.editingCleanupTask) {
        // 编辑现有任务
        const index = this.cleanupTasks.findIndex(
          (task) => task.id === this.cleanupTaskForm.id
        );
        if (index !== -1) {
          this.cleanupTasks[index] = {
            ...this.cleanupTaskForm,
            updateTime: this.getCurrentTime(),
          };
        }
      } else {
        // 添加新任务
        const newTask = {
          id: this.generateCleanupTaskId(),
          name: this.cleanupTaskForm.name,
          type: this.cleanupTaskForm.type,
          targetTable: this.cleanupTaskForm.targetTable,
          rule: this.cleanupTaskForm.rule,
          createTime: this.getCurrentTime(),
          status: this.cleanupTaskForm.executionMethod === "立即执行" ? "执行中" : "待执行",
        };
        this.cleanupTasks.unshift(newTask); // 添加到数组开头
      }

      // 保存到localStorage
      this.saveCleanupTasksToLocalStorage();

      this.showAddCleanupTaskModal = false;
      this.editingCleanupTask = false;
      // 重置表单
      this.resetCleanupTaskForm();
    },
    resetCleanupTaskForm() {
      this.cleanupTaskForm = {
        name: "",
        type: "",
        targetTable: "",
        rule: "",
        executionMethod: "立即执行",
        executionTime: "",
      };
    },
    fixAnomaly(anomaly) {
      this.currentAnomaly = anomaly;
      this.anomalyFixForm = {
        method: "手动修复",
        value: "",
        remark: "",
      };
      this.showFixAnomalyModal = true;
    },
    confirmFixAnomaly() {
      this.showFixAnomalyModal = false;
      // 从数据异常列表中移除已修复的异常
      this.dataAnomalies = this.dataAnomalies.filter(
        (a) => a.id !== this.currentAnomaly.id
      );
      // 保存到localStorage
      this.saveDataAnomaliesToLocalStorage();
    },
    ignoreAnomaly(anomaly) {
      // 从数据异常列表中移除已忽略的异常
      this.dataAnomalies = this.dataAnomalies.filter(
        (a) => a.id !== anomaly.id
      );
      // 保存到localStorage
      this.saveDataAnomaliesToLocalStorage();
    },
    // 保存数据异常到localStorage
    saveDataAnomaliesToLocalStorage() {
      try {
        localStorage.setItem(
          "dataManagementAnomalies",
          JSON.stringify(this.dataAnomalies)
        );
      } catch (e) {

      }
    },
    // 从localStorage加载数据异常
    loadDataAnomaliesFromLocalStorage() {
      try {
        const savedAnomalies = localStorage.getItem("dataManagementAnomalies");
        if (savedAnomalies) {
          this.dataAnomalies = JSON.parse(savedAnomalies);
        }
      } catch (e) {

      }
    },
    syncNow(source) {
      source.status = "同步中";
      source.lastSyncTime =
        "2025-07-08 " +
        new Date().getHours() +
        ":" +
        new Date().getMinutes() +
        ":00";
    },
    editDataSource(source) {
      this.editingDataSource = true;
      this.dataSourceForm = {
        id: source.id, // 保留原始数据源的ID
        name: source.name,
        type: source.type,
        connection: source.connection,
        username: source.username, // 保留用户名
        password: source.password, // 保留密码
        syncMethod: source.syncMethod,
        syncFrequency: source.syncFrequency,
      };
      this.showAddDataSourceModal = true;
    },
    // 修改删除数据源方法
    async deleteDataSource(source) {
      try {
        await ElMessageBox.confirm(
          `确定要删除数据源 "${source.name}" 吗？此操作不可恢复。`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
          }
        );
        this.dataSources = this.dataSources.filter((s) => s.id !== source.id);
        this.saveDataSourcesToLocalStorage();
        ElMessage.success('数据源删除成功');
      } catch (error) {
        // 用户点击取消

      }
    },
    saveDataSource() {
      // 添加表单验证
      if (!this.dataSourceForm.name) {
        ElMessage.warning("请输入数据源名称");
        return;
      }
      if (!this.dataSourceForm.type) {
        ElMessage.warning("请选择数据源类型");
        return;
      }
      if (!this.dataSourceForm.connection) {
        ElMessage.warning("请输入连接地址");
        return;
      }
      if (!this.dataSourceForm.username) {
        ElMessage.warning("请输入用户名");
        return;
      }
      if (!this.dataSourceForm.password) {
        ElMessage.warning("请输入密码");
        return;
      }
      if (!this.dataSourceForm.syncFrequency) {
        ElMessage.warning("请选择同步频率");
        return;
      }
      if (this.editingDataSource) {
        // 编辑现有数据源
        const index = this.dataSources.findIndex(
          (source) => source.id === this.dataSourceForm.id
        );
        if (index !== -1) {
          this.dataSources[index] = {
            ...this.dataSourceForm,
            lastSyncTime: this.dataSources[index].lastSyncTime, // 保留上次同步时间
            status: this.dataSources[index].status // 保留状态
          };
        }
      } else {
        // 添加新数据源
        const newDataSource = {
          id: this.generateDataSourceId(),
          name: this.dataSourceForm.name,
          type: this.dataSourceForm.type,
          connection: this.dataSourceForm.connection,
          username: this.dataSourceForm.username,
          password: this.dataSourceForm.password,
          syncMethod: this.dataSourceForm.syncMethod,
          syncFrequency: this.dataSourceForm.syncFrequency,
          lastSyncTime: "未同步",
          status: "正常"
        };
        this.dataSources.unshift(newDataSource); // 添加到数组开头
      }
      // 保存到localStorage
      this.saveDataSourcesToLocalStorage();
      this.showAddDataSourceModal = false;
      this.editingDataSource = false;
      this.dataSourceForm = {
        name: "",
        type: "",
        connection: "",
        username: "",
        password: "",
        syncMethod: "增量同步",
        syncFrequency: "每天",
      };
    },
    viewSyncLogDetail(log) {
      this.currentSyncLog = log;
      this.showSyncLogDetailModal = true;
    },
    retrySyncLog(log) {
      log.status = "进行中";
      log.startTime =
        "2025-07-08 " +
        String(new Date().getHours()).padStart(2, '0') +
        ":" +
        String(new Date().getMinutes()).padStart(2, '0') +
        ":00";
      log.endTime = "";
      log.duration = "";

      // 保存到localStorage
      this.saveSyncLogsToLocalStorage();

      this.showSyncLogDetailModal = false;

      // 模拟同步过程，3秒后更新状态
      setTimeout(() => {
        // 随机决定同步结果（80%成功率）
        const isSuccess = Math.random() > 0.2;

        log.status = isSuccess ? "成功" : "失败";
        log.endTime =
          "2025-07-08 " +
          String(new Date().getHours()).padStart(2, '0') +
          ":" +
          String(new Date().getMinutes()).padStart(2, '0') +
          ":" +
          String(new Date().getSeconds()).padStart(2, '0');

        // 计算持续时间
        const startTime = new Date(`2025-07-08 ${log.startTime.split(' ')[1]}`);
        const endTime = new Date(`2025-07-08 ${log.endTime.split(' ')[1]}`);
        const durationMs = endTime - startTime;

        // 转换为合适的时间格式
        if (durationMs < 60000) {
          log.duration = `${Math.floor(durationMs / 1000)}秒`;
        } else {
          const minutes = Math.floor(durationMs / 60000);
          const seconds = Math.floor((durationMs % 60000) / 1000);
          log.duration = `${minutes}分${seconds}秒`;
        }

        // 保存到localStorage
        this.saveSyncLogsToLocalStorage();
      }, 3000);
    },
    initCleanupCharts() {
      // 数据质量分析图表
      if (this.$refs.dataQualityChart) {
        const dataQualityChart = echarts.init(this.$refs.dataQualityChart);
        const dataQualityOption = {
          animation: false,
          tooltip: {
            trigger: "item",
            formatter: "{a} <br/>{b}: {c} ({d}%)",
          },
          legend: {
            orient: "vertical",
            left: 10,
            data: ["完整数据", "异常数据", "重复数据", "缺失数据"],
          },
          series: [
            {
              name: "数据质量",
              type: "pie",
              radius: ["50%", "70%"],
              avoidLabelOverlap: false,
              label: {
                show: false,
                position: "center",
              },
              emphasis: {
                label: {
                  show: true,
                  fontSize: "18",
                  fontWeight: "bold",
                },
              },
              labelLine: {
                show: false,
              },
              data: [
                { value: 2420, name: "完整数据" },
                { value: 56, name: "异常数据" },
                { value: 48, name: "重复数据" },
                { value: 44, name: "缺失数据" },
              ],
            },
          ],
        };
        dataQualityChart.setOption(dataQualityOption);
      }
      // 异常数据分布图表
      if (this.$refs.dataAnomalyChart) {
        const dataAnomalyChart = echarts.init(this.$refs.dataAnomalyChart);
        const dataAnomalyOption = {
          animation: false,
          tooltip: {
            trigger: "axis",
            axisPointer: {
              type: "shadow",
            },
          },
          legend: {
            data: ["数量"],
          },
          grid: {
            left: "3%",
            right: "4%",
            bottom: "18%",
            containLabel: true,
          },
          xAxis: {
            type: "category",
            data: [
              "数据缺失",
              "数据重复",
              "数据异常",
              "数据冲突",
              "数据不一致",
              "数据过期",
            ],
          },
          yAxis: {
            type: "value",
          },
          series: [
            {
              name: "数量",
              type: "bar",
              data: [8, 6, 4, 2, 3, 1],
            },
          ],
        };
        dataAnomalyChart.setOption(dataAnomalyOption);
      }
      // 数据完整性图表
      if (this.$refs.dataCompletenessChart) {
        const dataCompletenessChart = echarts.init(
          this.$refs.dataCompletenessChart
        );
        const dataCompletenessOption = {
          animation: false,
          tooltip: {
            trigger: "axis",
          },
          legend: {
            data: ["完整率"],
          },
          grid: {
            left: "3%",
            right: "4%",
            bottom: "18%",
            containLabel: true,
          },
          xAxis: {
            type: "category",
            boundaryGap: false,
            data: [
              "设备数据",
              "人员数据",
              "报警记录",
              "安全检查",
              "维护记录",
              "操作日志",
            ],
          },
          yAxis: {
            type: "value",
            axisLabel: {
              formatter: "{value}%",
            },
            max: 100,
          },
          series: [
            {
              name: "完整率",
              type: "line",
              data: [98.5, 96.2, 99.1, 97.8, 95.6, 99.8],
              markLine: {
                data: [
                  {
                    name: "标准线",
                    yAxis: 95,
                  },
                ],
              },
            },
          ],
        };
        dataCompletenessChart.setOption(dataCompletenessOption);
      }
    },
    initSyncCharts() {
      // 同步任务执行情况图表
      if (this.$refs.syncTaskChart) {
        const syncTaskChart = echarts.init(this.$refs.syncTaskChart);
        const syncTaskOption = {
          animation: false,
          tooltip: {
            trigger: "item",
            formatter: "{a} <br/>{b}: {c} ({d}%)",
          },
          legend: {
            orient: "vertical",
            left: 10,
            data: ["成功", "失败", "进行中"],
          },
          series: [
            {
              name: "同步状态",
              type: "pie",
              radius: ["50%", "70%"],
              avoidLabelOverlap: false,
              label: {
                show: false,
                position: "center",
              },
              emphasis: {
                label: {
                  show: true,
                  fontSize: "18",
                  fontWeight: "bold",
                },
              },
              labelLine: {
                show: false,
              },
              data: [
                { value: 36, name: "成功" },
                { value: 5, name: "失败" },
                { value: 1, name: "进行中" },
              ],
            },
          ],
        };
        syncTaskChart.setOption(syncTaskOption);
      }
      // 数据同步量趋势图表
      if (this.$refs.syncVolumeChart) {
        const syncVolumeChart = echarts.init(this.$refs.syncVolumeChart);
        const syncVolumeOption = {
          animation: false,
          tooltip: {
            trigger: "axis",
          },
          legend: {
            data: ["同步数据量"],
          },
          grid: {
            left: "3%",
            right: "4%",
            bottom: "18%",
            containLabel: true,
          },
          xAxis: {
            type: "category",
            boundaryGap: false,
            data: ["7/2", "7/3", "7/4", "7/5", "7/6", "7/7", "7/8"],
          },
          yAxis: {
            type: "value",
            axisLabel: {
              formatter: "{value}条",
              margin: 20,
            },
          },
          series: [
            {
              name: "同步数据量",
              type: "line",
              data: [1850, 1920, 2100, 2340, 2560, 2480, 2568],
              markPoint: {
                data: [
                  { type: "max", name: "最大值" },
                  { type: "min", name: "最小值" },
                ],
              },
            },
          ],
        };
        syncVolumeChart.setOption(syncVolumeOption);
      }
    },
    // 批量删除字段
    async batchDeleteFields() {
      if (!this.hasSelectedFields) {
        return;
      }
      const selectedCount = this.selectedFieldsCount;
      try {
        await ElMessageBox.confirm(
          `确定要删除选中的 ${selectedCount} 个字段吗？此操作不可恢复。`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
          }
        );
        this.fields = this.fields.filter((field) => !field.selected);
        this.saveFieldsToLocalStorage();
        ElMessage.success(`成功删除 ${selectedCount} 个字段`);
      } catch (error) {
        // 用户点击取消

      }
    },
    // 批量导出字段
    batchExportFields() {
      if (!this.hasSelectedFields) {
        return;
      }
      const selectedFields = this.fields.filter((field) => field.selected);
      // ... 导出逻辑
      ElMessage.success(`成功导出 ${selectedFields.length} 个字段数据`);
    },
    // 如果需要支持其他格式导出，可以添加以下方法
    batchExportFieldsAsCSV() {
      if (!this.hasSelectedFields) {
        return;
      }
      const selectedFields = this.fields.filter((field) => field.selected);
      // CSV 表头
      const headers = [
        "字段名称",
        "字段标识",
        "数据类型",
        "是否必填",
        "字段描述",
        "状态",
        "更新时间",
      ];

      // CSV 数据行
      const csvRows = selectedFields.map((field) => [
        field.name,
        field.identifier,
        field.dataType,
        field.isRequired ? "是" : "否",
        `"${field.description.replace(/"/g, '""')}"`, // 处理描述中的引号
        field.status,
        field.updateTime,
      ]);

      // 构建 CSV 内容
      const csvContent = [
        headers.join(","),
        ...csvRows.map((row) => row.join(",")),
      ].join("\n");

      // 创建下载链接
      const blob = new Blob(["\uFEFF" + csvContent], {
        type: "text/csv;charset=utf-8;",
      });
      const link = document.createElement("a");
      const url = URL.createObjectURL(blob);
      link.setAttribute("href", url);
      link.setAttribute(
        "download",
        `字段数据_${new Date().toISOString().split("T")[0]}.csv`
      );
      link.style.visibility = "hidden";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
  },
};
</script>
<style scoped>
/* 隐藏input number的箭头 */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input[type="number"] {
  -moz-appearance: textfield;
}

/* 自定义颜色类 */
.bg-teal-100 {
  background-color: #b2f5ea;
}

.text-teal-600 {
  color: #319795;
}

.text-teal-800 {
  color: #285e61;
}

.bg-indigo-100 {
  background-color: #e5edff;
}

.text-indigo-600 {
  color: #5a67d8;
}

.text-indigo-800 {
  color: #434190;
}
</style>
